Hidden features of VBA Hidden features of VBA vba vba

Hidden features of VBA


This trick only works in Access VBA, Excel and others won't allow it. But you can make a Standard Module hidden from the object browser by prefixing the Module name with an underscore. The module will then only be visible if you change the object browser to show hidden objects.

This trick works with Enums in all vb6 based version of VBA. You can create a hidden member of an Enum by encasing it's name in brackets, then prefixing it with an underscore. Example:

Public Enum MyEnum    meDefault = 0    meThing1 = 1    meThing2 = 2    meThing3 = 3    [_Min] = meDefault     [_Max] = meThing3 End EnumPublic Function IsValidOption(ByVal myOption As MyEnum) As Boolean    If myOption >= MyEnum.[_Min] Then IsValidOption myOption <= MyEnum.[_Max]End Function

In Excel-VBA you can reference cells by enclosing them in brackets, the brackets also function as an evaluate command allowing you to evaluate formula syntax:

Public Sub Example()    [A1] = "Foo"    MsgBox [VLOOKUP(A1,A1,1,0)]End Sub

Also you can pass around raw data without using MemCopy (RtlMoveMemory) by combining LSet with User Defined Types of the same size:

Public Sub Example()    Dim b() As Byte    b = LongToByteArray(8675309)    MsgBox b(1)End SubPrivate Function LongToByteArray(ByVal value As Long) As Byte()    Dim tl As TypedLong    Dim bl As ByteLong    tl.value = value    LSet bl = tl    LongToByteArray = bl.valueEnd Function

Octal & Hex Literals are actually unsigned types, these will both output -32768:

Public Sub Example()    Debug.Print &H8000    Debug.Print &O100000End Sub

As mentioned, passing a variable inside parenthesis causes it to be passed ByVal:

Sub PredictTheOutput()    Dim i&, j&, k&    i = 10: j = i: k = i    MySub (i)    MySub j    MySub k + 20    MsgBox Join(Array(i, j, k), vbNewLine), vbQuestion, "Did You Get It Right?"End SubPublic Sub MySub(ByRef foo As Long)    foo = 5End Sub

You can assign a string directly into a byte array and vice-versa:

Public Sub Example()    Dim myString As String    Dim myBytArr() As Byte    myBytArr = "I am a string."    myString = myBytArr    MsgBox myStringEnd Sub

"Mid" is also an operator. Using it you overwrite specific portions of strings without VBA's notoriously slow string concatenation:

Public Sub Example1()    ''// This takes about 47% of time Example2 does:    Dim myString As String    myString = "I liek pie."    Mid(myString, 5, 2) = "ke"    Mid(myString, 11, 1) = "!"    MsgBox myStringEnd SubPublic Sub Example2()    Dim myString As String    myString = "I liek pie."    myString = "I li" & "ke" & " pie" & "!"    MsgBox myStringEnd Sub


There is an important but almost always missed feature of the Mid() statement. That is where Mid() appears on the left hand side of an assignment as opposed to the Mid() function that appears in the right hand side or in an expression.

The rule is that if the if the target string is not a string literal, and this is the only reference to the target string, and the length of segment being inserted matches the length of the segment being replaced, then the string will be treated as mutable for the operation.

What does that mean? It means that if your building up a large report or a huge list of strings into a single string value, then exploiting this will make your string processing much faster.

Here is a simple class that benefits from this. It gives your VBA the same StringBuilder capability that .Net has.

' Class: StringBuilderOption ExplicitPrivate Const initialLength As Long = 32Private totalLength As Long  ' Length of the bufferPrivate curLength As Long    ' Length of the string value within the bufferPrivate buffer As String     ' The bufferPrivate Sub Class_Initialize()  ' We set the buffer up to it's initial size and the string value ""  totalLength = initialLength  buffer = Space(totalLength)  curLength = 0End SubPublic Sub Append(Text As String)  Dim incLen As Long ' The length that the value will be increased by  Dim newLen As Long ' The length of the value after being appended  incLen = Len(Text)  newLen = curLength + incLen  ' Will the new value fit in the remaining free space within the current buffer  If newLen <= totalLength Then    ' Buffer has room so just insert the new value    Mid(buffer, curLength + 1, incLen) = Text  Else    ' Buffer does not have enough room so    ' first calculate the new buffer size by doubling until its big enough    ' then build the new buffer    While totalLength < newLen      totalLength = totalLength + totalLength    Wend    buffer = Left(buffer, curLength) & Text & Space(totalLength - newLen)  End If  curLength = newLenEnd SubPublic Property Get Length() As Integer  Length = curLengthEnd PropertyPublic Property Get Text() As String  Text = Left(buffer, curLength)End PropertyPublic Sub Clear()  totalLength = initialLength  buffer = Space(totalLength)  curLength = 0End Sub

And here is an example on how to use it:

  Dim i As Long  Dim sb As StringBuilder  Dim result As String  Set sb = New StringBuilder  For i = 1 to 100000    sb.Append CStr( i)  Next i  result = sb.Text


VBA itself seems to be a hidden feature. Folks I know who've used Office products for years have no idea it's even a part of the suite.

I've posted this on multiple questions here, but the Object Browser is my secret weapon. If I need to ninja code something real quick, but am not familiar with the dll's, Object Browser saves my life. It makes it much easier to learn the class structures than MSDN.

The Locals Window is great for debugging as well. Put a pause in your code and it will show you all the variables, their names, and their current values and types within the current namespace.

And who could forget our good friend Immediate Window? Not only is it great for Debug.Print standard output, but you can enter in commands into it as well. Need to know what VariableX is?

?VariableX

Need to know what color that cell is?

?Application.ActiveCell.Interior.Color

In fact all those windows are great tools to be productive with VBA.