What's difference between
Len(Me.txtStartDate.Value & vbNullString) = 0
and
Len(Me.txtStartDate.Value) = 0
What's difference between
Len(Me.txtStartDate.Value & vbNullString) = 0
and
Len(Me.txtStartDate.Value) = 0
vbNullString
is essentially a null string pointer.
Debug.Print StrPtr(vbNullString) 'prints 0
It looks equivalent to a literal ""
empty string, but it's not:
Debug.Print StrPtr("") 'prints an address; 6 bytes are allocated for it
There is practically no difference between your two examples... but only because Me.txtStartDate.Value
is already a String
.
If you were doing this:
Debug.Print Sheet1.Range("A1").Value & vbNullString
Then you would be doing an implicit type conversion between whatever type is returned by Sheet1.Range("A1").Value
(say, a Date
, or a Double
) by means of string concatenation, because the &
operator is only used for string concatenations, and the result of that expression will be a String
.
In other words, it's a rather convoluted way to do this:
Debug.Print CStr(Sheet1.Range("A1").Value)
Or, as litelite mentioned, a rather convoluted way to do this:
Len(CStr(Me.txtStartDate.Value)) = 0
You typically use vbNullString
in place of an empty string ""
literal, to spare uselessly allocating 6 bytes (4 for the string pointer, 2 for the null character), and to make your code unambiguously clear about your intent (e.g. "I mean an empty string, this wasn't a typo"), similar to how you would use string.Empty
in C#.
What is vbNullString
? It is one strange bird, which exists solely for calling functions in a DLL that were written in C (or C++).
Take a look at http://vb.mvps.org/tips/varptr/. It describes a set of (now hidden) functions in VBA (and VB6) that exist solely to allow the passing of pointers to the contents of variables, again mostly to functions in a DLL that were written in C (or any other language that does pointers).
(Technically, VBA does not do pointers, so any pointer that may be returned by a function is - technically speaking - casted to a long integer. ByRef
and With
do involve pointers, of course, but in hidden-behind-the-scene ways.)
In particular, try out StrPtr(vbNullString)
; it will return 0
. If you tried instead StrPtr("")
, you would get some non-zero result. The result is a pointer to where the characters of a string really are in memory. However, a pointer of 0 means something special in C (and C++) - it is often called the NULL pointer (or simply NULL, or maybe null), and it is meant to signify that a pointer points to nowhere. In C programming, sometimes a coder would like to allow a pointer parameter being NULL to mean something special for a function.
If you tried StrPtr("")
a few times in a row, you'll likely get a few different non-zero results. That's because VBA is creating a brand new empty string for each try, and as weird as it seems that any memory should be used for a string that is empty, remember that a string in VBA includes a long integer that indicates the number of characters in the string.
Ok guys my 2 cents on the old topic which has been commented on many times.
First vbNullString and vbNullChar are constants, names of some bytes already allocated in memory. That is why when you use vbNullString instead of "" it indeed saves some bytes memory because "" will allocate an empty string, at least temporarily, which also takes some cpu cycles.
You may try for yourself. Using vbNullString is 3x faster.
Private Declare PtrSafe Function QueryPerformanceFrequency _
Lib "kernel32.dll" (ByRef lpPFreq As Currency _
) As Boolean
Private Declare PtrSafe Function QueryPerformanceCounter _
Lib "kernel32.dll" (ByRef lpPCount As Currency _
) As Boolean
Sub Test()
Dim t0 As Currency, t As Currency, f As Currency
Dim s As String
Dim i As Long
QueryPerformanceFrequency f
QueryPerformanceCounter t0
For i = 1 To 10 ^ 6
s = ""
Next
QueryPerformanceCounter t
Debug.Print 1000 * (t - t0) / f; "ms"
QueryPerformanceCounter t0
For i = 1 To 10 ^ 6
s = vbNullString
Next
QueryPerformanceCounter t
Debug.Print 1000 * (t - t0) / f; "ms"
End Sub
The vbNullString constant is a String which can be easily proven by trying:
Debug.print LenB(vbNullstring) ' prints 0
Debug.print VarPtr(vbNullstring) ' prints 8 (= vbString)
The vbNullChar constant is also a string. Try:
Debug.print LenB(vbNullChar) ' prints 2
Debug.print VarPtr(vbNullChar) ' print 8 (= vbString)
Which will print 2 (= 2 bytes) and 8 (vbString).
Secondly vbNullString
is thus not a pointer. VB/VBA doesn't do pointers so a null pointer constant is not defined.
However, I use pointers a lot and therefore I define:
Const vbNullPtr As LongPtr = 0
Debug.print VarPtr(vbNullPtr ) ' print 20 (x64) and 4 (x32)
So using vbNullString instead of vbNullPtr works correctly when dealing with pointers because VB/VBA converts automatically. However, it is not very neat.
So further straightforward points about the vbNullString
beast.
Debug.Print StrPtr(vbNullString) ' prints 0
Likewise:
Dim s as String
Debug.Print StrPtr(s) 'prints 0
Here s is a string variable holding the 0 address. After a string is allocated the StrPtr(s)
will be the BSTR pointer.
Dim s as String: v = ""
Debug.Print StrPtr(s) ' prints BSTR address
Now the string variable stores the address of the allocated BSTR which holds 0 bytes but needs 6 bytes to hold the BSTR structure.
Let me know what you think. This may all be somewhat futile but I like to get things right.