Paul Kelly's Blog, page 2
July 13, 2015
The Ultimate Guide to VBA String Functions
String operationsFunction(s)
Append two or more stringsFormat or "&"
Build a string from an arrayJoin
Compare - normalStrComp or "="
Compare - patternLike
Convert to a stringCStr, Str
Convert string to dateSimple: CDate
Advanced: Format
Convert string to numberSimple: CLng, CInt, CDbl, Val
Advanced: Format
Convert to unicode, wide, narrowStrConv
Convert to upper/lower caseStrConv, UCase, LCase
Extract part of a stringLeft, Right, Mid
Format a stringFormat
Find characters in a stringInStr, InStrRev
Generate a stringString
Get length of a stringLen
Remove blanksLTrim, RTrim, Trim
Replace part of a stringReplace
Reverse a stringStrReverse
Parse string to array Split
Introduction
Using strings is a very important part of VBA. There are many types of manipulation you may wish to do with strings. These include tasks such as
extracting part of a string
comparing strings
converting numbers to a string
formatting a date to include weekday
finding a character in a string
removing blanks
parsing to an array
and so on
The good news is that VBA contains plenty of functions to help you perform these tasks with ease.
This post provides an in-depth guide to using string in VBA. It explains strings in simple terms with clear code examples. I have laid it out so the post can be easily used as a quick reference guide.
If you are going to use strings a lot then I recommend you read the first section as it applies to a lot of the functions. Otherwise you can read in order or just go to the section you require.

© Ra2studio | Dreamstime.com
Read This First!
The following two points are very important when dealing with VBA string functions.
The Original String is not Changed
An important point to remember is that the VBA string functions do not change the original string. They return a new string with the changes the function made. If you want to change the original string you simply assign the result to the original string. See the section Extracting Part of a String for examples of this.
How To Use Compare
Some of the string functions such as StrComp() and Instr() etc. have an optional Compare parameter. This works as follows:
vbTextCompare: Upper and lower case are considered the same
vbBinaryCompare: Upper and lower case are considered different
The following code uses the string comparison function StrComp() to demonstrate the Compare parameter
Sub Comp1()
' Prints 0 : Strings match
Debug.Print StrComp("ABC", "abc", vbTextCompare)
' Prints -1 : Strings do not match
Debug.Print StrComp("ABC", "abc", vbBinaryCompare)
End Sub
You can use the Option Compare setting instead of having to use this parameter each time. Option Compare is set at the top of a Module. Any function that uses the Compare parameter will take this setting as the default. The two ways to use Option Compare are:
1. Option Compare Text: makes vbTextCompare the default Compare argument
Option Compare Text
Sub Comp2()
' Strings match - uses vbCompareText as Compare argument
Debug.Print StrComp("ABC", "abc")
Debug.Print StrComp("DEF", "def")
End Sub
2. Option Compare Binary: Makes vbBinaryCompare the default Compare argument
Option Compare Binary
Sub Comp2()
' Strings do not match - uses vbCompareBinary as Compare argument
Debug.Print StrComp("ABC", "abc")
Debug.Print StrComp("DEF", "def")
End Sub
If Option Compare is not used then the default is Option Compare Binary.
Now that you understand these two important points about string we can go ahead and look at the string functions individually.
Appending Strings

ABC Cube Pile © Aleksandr Atkishkin | Dreamstime.com
You can append strings using the & operator. The following code shows some examples of using it
Sub Append()
Debug.Print "ABC" & "DEF"
Debug.Print "Jane" & " " & "Smith"
Debug.Print "Long " & 22
Debug.Print "Double " & 14.99
Debug.Print "Date " & #12/12/2015#
End Sub
You can see in the example that different types such as dates and number are automatically converted to strings. You may see the operator being used to append strings. The difference is that this operator will only work with string types. If you try to use it with other type you will get an error.
' This will give the error message: "Type Mismatch"
Debug.Print "Long " 22
If you want to do more complex appending of strings then you may wish to use the Format function described below.
Extracting Part of a String
The functions discussed in this section are useful when dealing with basic extracting from a string. For anything more complicated you might want to check out my post on How to Easily Extract From Any String Without Using VBA InStr.
FunctionParamsDescriptionExample
Leftstring, lengthReturn chars from left sideLeft("John Smith",4)
Rightstring, lengthReturn chars from right sideRight("John Smith",5)
Midstring, start, lengthReturn chars from middleMid("John Smith",3,2)
The Left, Right, and Mid functions are used to extract parts of a string. They are very simple functions to use. Left reads characters from the left, Right from the right and Mid from a starting point that you specify.
Sub UseLeftRightMid()
Dim sCustomer As String
sCustomer = "John Thomas Smith"
Debug.Print Left(sCustomer, 4) ' Prints: John
Debug.Print Right(sCustomer, 5) ' Prints: Smith
Debug.Print Left(sCustomer, 11) ' Prints: John Thomas
Debug.Print Right(sCustomer, 12) ' Prints: Thomas Smith
Debug.Print Mid(sCustomer, 1, 4) ' Prints: John
Debug.Print Mid(sCustomer, 6, 6) ' Prints: Thomas
Debug.Print Mid(sCustomer, 13, 5) ' Prints: Smith
End Sub
As mentioned in the previous section, VBA string functions do not change the original string. Instead, they return the result as a new string.
In the next example you can see that the string Fullname was not changed after using the Left function
Sub UsingLeftExample()
Dim Fullname As String
Fullname = "John Smith"
Debug.Print "Firstname is: "; Left(Fullname, 4)
' Original string has not changed
Debug.Print "Fullname is: "; Fullname
End Sub
If you want to change the original string you simply assign it to the return value of the function
Sub ChangingString()
Dim name As String
name = "John Smith"
' Assign return string to the name variable
name = Left(name, 4)
Debug.Print "Name is: "; name
End Sub
Searching Within a String
FunctionParamsDescriptionExample
InStrString1, String2Finds position of stringInStr("John Smith","h")
InStrRevStringCheck, StringMatchFinds position of string from endInStrRev("John Smith","h")
InStr and InStrRev are VBA functions used to search through strings for a substring. If the search string is found then the position(from the start of the check string) of the search string is returned. If the search string is not found then zero is returned. If either string is null then null is returned.
InStr Description of Parameters
InStr() Start[Optional], String1, String2, Compare[Optional]
Start As Long[Optional – Default is 1]: This is a number that specifies the starting search position from the left
String1 As String: The string to search
String2 As String: The string to search for
Compare As vbCompareMethod : See the section on Compare above for more details
InStr Use and Examples
InStr returns the first position in a string where a given substring is found. The following shows some examples of using it
Sub FindSubString()
Dim name As String
name = "John Smith"
' Returns 3 - position of first h
Debug.Print InStr(name, "h")
' Returns 10 - position of first h starting from position 4
Debug.Print InStr(4, name, "h")
' Returns 8
Debug.Print InStr(name, "it")
' Returns 6
Debug.Print InStr(name, "Smith")
' Returns 0 - string "SSS" not found
Debug.Print InStr(name, "SSS")
End Sub
InStrRev Description of Parameters
InStrRev() StringCheck, StringMatch, Start[Optional], Compare[Optional]
StringCheck As String: The string to search
StringMatch: The string to search for
Start As Long[Optional – Default is -1]: This is a number that specifies the starting search position from the right
Compare As vbCompareMethod: See the section on Compare above for more details
InStrRev Use and Examples
The InStrRev function is the same as InStr except that it searches from the end of the string. It’s important to note that the position returned is the position from the start. Therefore if there is only one instance of the search item then both InStr() and InStrRev() will return the same value.
The following code show some examples of using InStrRev
Sub UsingInstrRev()
Dim name As String
name = "John Smith"
' Both Return 1 - position of the only J
Debug.Print InStr(name, "J")
Debug.Print InStrRev(name, "J")
' Returns 10 - second h
Debug.Print InStrRev(name, "h")
' Returns 3 - first h as searches from position 9
Debug.Print InStrRev(name, "h", 9)
' Returns 1
Debug.Print InStrRev(name, "John")
End Sub
The InStr and InStrRev functions are useful when dealing with basic string searches. However, if you are going to use them for extracting text from a string they can make things complicated. I have written about a much better way to do this in my post How to Easily Extract From Any String Without Using VBA InStr.
Removing Blanks
FunctionParamsDescriptionExample
LTrimstringRemoves spaces from leftLTrim(" John ")
RTrimstringRemoves spaces from rightRTrim(" John ")
TrimstringRemoves Spaces from left and rightTrim(" John ")
The Trim functions are simple functions that remove spaces from either the start or end of a string.
Trim Functions Use and Examples
LTrim removes spaces from the left of a string
RTrim removes spaces from the right of a string
Trim removes spaces from the left and right of a string
Sub TrimStr()
Dim name As String
name = " John Smith "
' Prints "John Smith "
Debug.Print LTrim(name)
' Prints " John Smith"
Debug.Print RTrim(name)
' Prints "John Smith"
Debug.Print Trim(name)
End Sub
Length of a String
FunctionParamsDescriptionExample
LenstringReturns length of stringLen ("John Smith")
Len is a simple function when used with a string. It simply returns the number of characters the string contains. If used with a numeric type such as long it will return the number of bytes.
Sub GetLen()
Dim name As String
name = "John Smith"
' Prints 10
Debug.Print Len("John Smith")
' Prints 3
Debug.Print Len("ABC")
' Prints 4 as Long is 4 bytes in size
Dim total As Long
Debug.Print Len(total)
End Sub
Reversing a String
FunctionParamsDescriptionExample
StrReversestringReverses a stringStrReverse ("John Smith")
StrReverse is another easy-to-use function. It simply returns the given string with the characters reversed.
Sub RevStr()
Dim s As String
s = "Jane Smith"
' Prints: htimS enaJ
Debug.Print StrReverse(s)
End Sub
Comparing Strings
FunctionParamsDescriptionExample
StrCompstring1, string2Compares 2 stringsStrComp ("John", "John")
The function StrComp is used to compare two strings. The following subsections describe how it is used.
Description of Parameters
StrComp() String1, String2, Compare[Optional]
String1 As String: The first string to compare
String2 As String: The second string to compare
Compare As vbCompareMethod : See the section on Compare above for more details
StrComp Return Values
Return ValueDescription
0Strings match
-1string1 less than string2
1string1 greater than string2
Nullif either string is null
Use and Examples
The following are some examples of using the StrComp function
Sub UsingStrComp()
' Returns 0
Debug.Print StrComp("ABC", "ABC", vbTextCompare)
' Returns 1
Debug.Print StrComp("ABCD", "ABC", vbTextCompare)
' Returns -1
Debug.Print StrComp("ABC", "ABCD", vbTextCompare)
' Returns Null
Debug.Print StrComp(Null, "ABCD", vbTextCompare)
End Sub
Compare Strings using Operators
You can also use the equals sign to compare strings. The difference between the equals comparison and the StrComp function are:
The equals sign returns only true or false.
You cannot specify a Compare parameter using the equal sign – it uses the “Option Compare” setting.
The following shows some examples of using equals to compare strings
Option Compare Text
Sub CompareUsingEquals()
' Returns true
Debug.Print "ABC" = "ABC"
' Returns true because "Compare Text" is set above
Debug.Print "ABC" = "abc"
' Returns false
Debug.Print "ABCD" = "ABC"
' Returns false
Debug.Print "ABC" = "ABCD"
' Returns null
Debug.Print Null = "ABCD"
End Sub
The Operator “<>” means “does not equal”. It is essentially the opposite of using the equals sign as the following code shows
Option Compare Text
Sub CompareWithNotEqual()
' Returns false
Debug.Print "ABC" <> "ABC"
' Returns true because "Compare Text" is set above
Debug.Print "ABC" <> "abc"
' Returns true
Debug.Print "ABCD" <> "ABC"
' Returns true
Debug.Print "ABC" <> "ABCD"
' Returns null
Debug.Print Null <> "ABCD"
End Sub
Comparing Strings using Pattern Matching
OperatorParamsDescriptionExample
Likestring, string patternchecks if string has the given pattern"abX" Like "??X"
"54abc5" Like "*abc#"
TokenMeaning
?Any single char
#Any single digit(0-9)
*zero or more characters
[charlist]Any char in the list
[!charlist]Any char not in the char list
Pattern matching is used to determine if a string has a particular pattern of characters. For example, you may want to check that a customer number has 3 digits followed by 3 alphabetic characters or a string has the letters XX followed by any number of characters.
If the string matches the pattern then the return value is true, otherwise it is false.
Pattern matching is similar to the VBA Format function in that there are almost infinite ways to use it. In this section I am going to give some examples that will explain how it works. This should cover the most common uses. If you need more information about pattern matching you can refer to the MSDN Page for the Like operator.
Lets have a look at a basic example using the tokens. Take the following pattern string
[abc][!def]?#X*
Let’s look at how this string works
[abc] a character that is either a,b or c
[!def] a character that is not d,e or f
? any character
# any digit
X the character X
* followed by zero or more characters
Therefore the following string is valid
apY6X
a is one of abc
p is not one of the characters d, e or f
Y is any character
6 is a digit
X is the letter X
The following code examples show the results of various strings with this pattern
Sub Patterns()
' True
Debug.Print 1; "apY6X" Like "[abc][!def]?#X*"
' True - any combination of chars after x is valid
Debug.Print 2; "apY6Xsf34FAD" Like "[abc][!def]?#X*"
' False - char d not in [abc]
Debug.Print 3; "dpY6X" Like "[abc][!def]?#X*"
' False - 2nd char e is in [def]
Debug.Print 4; "aeY6X" Like "[abc][!def]?#X*"
' False - A at position 4 is not a digit
Debug.Print 5; "apYAX" Like "[abc][!def]?#X*"
' False - char at position 5 must be X
Debug.Print 1; "apY6Z" Like "[abc][!def]?#X*"
End Sub
Real-World Example of Pattern Matching
To see a real-world example of using pattern matching check out .
Important Note on VBA Pattern Matching
The Like operator uses either Binary or Text comparison based on the Option Compare setting. Please see the section on Compare above for more details.
Replace Part of a String
FunctionParamsDescriptionExample
Replacestring, find, replace,
start, count, compareReplaces a substring with a substringReplace ("Jon","n","hn")
Replace is used to replace a substring in a string by another substring. It replaces all instances of the substring that are found by default.
Replace Description of Parameters
Replace() Expression, Find, Replace, Start[Optional], Count[Optional], Compare[Optional]
Expression As String: The string to replace chars in
Find As String: The substring to replace in the Expression string
Replace As String: The string to replace the Find substring with
Start As Long[Optional – Default is 1]: The start position in the string
Count As Long[Optional – Default is -1]: The number of substitutions to make. The default -1 means all.
Compare As vbCompareMethod : See the section on Compare above for more details
Use and Examples
The following code shows some examples of using the Replace function
Sub ReplaceExamples()
' Replaces all the question marks with(?) with semi colons(;)
Debug.Print Replace("A?B?C?D?E", "?", ";")
' Replace Smith with Jones
Debug.Print Replace("Peter Smith,Ann Smith", "Smith", "Jones")
' Replace AX with AB
Debug.Print Replace("ACD AXC BAX", "AX", "AB")
End Sub
Output
A;B;C;D;E
Peter Jones,Sophia Jones
ACD ABC BAB
In the following examples we use the Count optional parameter. Count determines the number of substitutions to make. So for example, setting Count equal to one means that only the first occurrence will be replaced.
Sub ReplaceCount()
' Replaces first question mark only
Debug.Print Replace("A?B?C?D?E", "?", ";", Count:=1)
' Replaces first three question marks
Debug.Print Replace("A?B?C?D?E", "?", ";", Count:=3)
End Sub
Output
A;B?C?D?E
A;B;C;D?E
The Start optional parameter allow you to return part of a string. The position you specify using Start is where it starts returning the string from. It will not return any part of the string before this position whether a replace was made or not.
Sub ReplacePartial()
' Use original string from position 4
Debug.Print Replace("A?B?C?D?E", "?", ";", Start:=4)
' Use original string from position 8
Debug.Print Replace("AA?B?C?D?E", "?", ";", Start:=8)
' No item replaced but still only returns last 2 characters
Debug.Print Replace("ABCD", "X", "Y", Start:=3)
End Sub
Output
;C;D;E
;E
CD
Sometimes you may only want to replace only upper or lower case letters. You can use the Compare parameter to do this. This is used in a lot of string functions. For more information on this check out the Compare section above.
Sub ReplaceCase()
' Replace capital A's only
Debug.Print Replace("AaAa", "A", "X", Compare:=vbBinaryCompare)
' Replace All A's
Debug.Print Replace("AaAa", "A", "X", Compare:=vbTextCompare)
End Sub
Output
XaXa
XXXX
Multiple Replaces
If you want to replace multiple values in a string you can nest the calls. In the following code we want to replace X and Y with A and B respectively.
Sub ReplaceMulti()
Dim newString As String
' Replace A with X
newString = Replace("ABCD ABDN", "A", "X")
' Now replace B with Y in new string
newString = Replace(newString, "B", "Y")
Debug.Print newString
End Sub
In the next example we will change the above code to perform the same task. We will use the return value of the first replace as the argument for the second replace.
Sub ReplaceMultiNested()
Dim newString As String
' Replace A with X and B with Y
newString = Replace(Replace("ABCD ABDN", "A", "X"), "B", "Y")
Debug.Print newString
End Sub
The result of both of these Subs is
XYCD XYDN
Convert Types to String(Basic)
This section is about converting numbers to a string. A very important point here is that most the time VBA will automatically convert to a string for you. Let’s look at some examples
Sub AutoConverts()
Dim s As String
' Automatically converts number to string
s = 12.99
Debug.Print s
' Automatically converts multiple numbers to string
s = "ABC" & 6 & 12.99
Debug.Print s
' Automatically converts double variable to string
Dim d As Double, l As Long
d = 19.99
l = 55
s = "Values are " & d & " " & l
Debug.Print s
End Sub
When you run the above code you can see that the number were automatically converted to strings. So when you assign a value to a string VBA will look after the conversion for you most of the time. There are conversion functions in VBA and in the following sub sections we will look at the reasons for using them.
Explicit Conversion
FunctionParamsDescriptionExample
CStrexpressionConverts a number variable to a stringCStr ("45.78")
StrnumberConverts a number variable to a stringStr ("45.78")
In certain cases you may want to convert an item to a string without have to place it in a string variable first. In this case you can use the Str or CStr functions. Both take an expression as a function and this can be any type such as long, double, data or boolean.
Let’s look at a simple example. Imagine you are reading a list of values from different types of cells to a collection. You can use the Str/CStr functions to ensure they are all stored as strings. The following code shows an example of this
Sub UseStr()
Dim coll As New Collection
Dim c As Range
' Read cell values to collection
For Each c In Range("A1:A10")
' Use Str to convert cell value to a string
coll.Add Str(c)
Next
' Print out the collection values and type
Dim i As Variant
For Each i In coll
Debug.Print i, TypeName(i)
Next
End Sub
In the above example we use Str to convert the value of the cell to a string. The alternative to this would be to assign the value to a string and then assigning the string to the collection. So you can see that using Str here is much more efficient.
Multi Region
The difference between the Str and CStr functions is that CStr converts based on the region. If your macros will be used in multiple regions then you will need to use CStr for you string conversions.
It is good practise to use CStr when reading values from cells. If your code ends up being used in another region then you will not have to make any changes to make it work correctly.
Convert String to Number- CLng, CDbl, Val etc.
FunctionReturnsExample
CBoolBooleanCBool("True"), CBool("0")
CCurCurrencyCCur("245.567")
CDateDateCDate("1/1/2017")
CDblDoubleCCur("245.567")
CDecDecimalCDec("245.567")
CIntIntegerCInt("45")
CLngLong IntegerCLng("45.78")
CVarVariantCVar("")
The above functions are used to convert strings to various types. If you are assigning to a variable of this type then VBA will do the conversion automatically.
Sub StrToNumeric()
Dim l As Long, d As Double, c As Currency
Dim s As String
s = "45.923239"
l = s
d = s
c = s
Debug.Print "Long is "; l
Debug.Print "Double is "; d
Debug.Print "Currency is "; c
End Sub
Using the conversion types gives more flexibility. It means you can determine the type at runtime. In the following code we set the type based on the sType argument passed to the PrintValue function. As this type can be read from an external source such as a cell, we can set the type at runtime. If we declare a variable as Long then it will always be long when the code runs.
Sub Test()
' Prints 46
PrintValue "45.56", "Long"
' Print 45.56
PrintValue "45.56", ""
End Sub
Sub PrintValue(ByVal s As String, ByVal sType As String)
Dim value
' Set the data type based on a type string
If sType = "Long" Then
value = CLng(s)
Else
value = CDbl(s)
End If
Debug.Print "Type is "; TypeName(value); value
End Sub
If a string is not a valid number(i.e. contains symbols other numeric) then you get a “Type Mismatch” error.
Sub InvalidNumber()
Dim l As Long
' Will give type mismatch error
l = CLng("45A")
End Sub
The Val Function
The value function convert numeric parts of a string to the correct number type.
The Val function converts the first numbers it meets. Once it meets letters in a string it stops. If there are only letters then it returns zero as the value. The following code shows some examples of using Val
Sub UseVal()
' Prints 45
Debug.Print Val("45 New Street")
' Prints 45
Debug.Print Val(" 45 New Street")
' Prints 0
Debug.Print Val("New Street 45")
' Prints 12
Debug.Print Val("12 f 34")
End Sub
The Val function has two disadvantages
1. Not Multi-Region – Val does not recognise international versions of numbers such as using commas instead of decimals. Therefore you should use the above conversion functions when you application will be used in multiple regions.
2. Converts invalid strings to zero – This may be okay in some instances but in most cases it is better if an invalid string raises an error. The application is then aware there is a problem and can act accordingly. The conversion functions such as CLng will raise an error if the string contains non-numeric characters.
Generate a String of items – String Function
FunctionParamsDescriptionExample
Stringnumber, characterConverts a number variable to a stringString (5,"*")
The String function is used to generate a string of repeated characters. The first argument is the number of times to repeat it, the second argument is the character.
Sub GenString()
' Prints: AAAAA
Debug.Print String(5, "A")
' Prints: >>>>>
Debug.Print String(5, 62)
' Prints: (((ABC)))
Debug.Print String(3, "(") & "ABC" & String(3, ")")
End Sub
Convert Case/Unicode – StrConv, UCase, LCase
FunctionParamsDescriptionExample
StrConvstring, conversion, LCIDConverts a StringStrConv("abc",vbUpperCase)
If you want to convert the case of a string to upper or lower you can use the UCase and LCase functions for upper and lower respectively. You can also use the StrConv function with the vbUpperCase or vbLowerCase argument. The following code shows example of using these three functions
Sub ConvCase()
Dim s As String
s = "Mary had a little lamb"
' Upper
Debug.Print UCase(s)
Debug.Print StrConv(s, vbUpperCase)
' Lower
Debug.Print LCase(s)
Debug.Print StrConv(s, vbLowerCase)
' Sets the first letter of each word to upper case
Debug.Print StrConv(s, vbProperCase)
End Sub
Output
MARY HAD A LITTLE LAMB
MARY HAD A LITTLE LAMB
mary had a little lamb
mary had a little lamb
Mary Had A Little Lamb
Other Conversions
As well as case the StrConv can perform other conversions based on the Conversion parameter. The following table shows a list of the different parameter values and what they do. For more information on StrConv check out the MSDN Page.
ConstantValueConverts
vbUpperCase1to upper case
vbLowerCase2to lower case
vbProperCase3first letter of each word to uppercase
vbWide*4from Narrow to Wide
vbNarrow*8from Wide to Narrow
vbKatakana**16from Hiragana to Katakana
vbHiragana32from Katakana to Hiragana
vbUnicode64to unicode
vbFromUnicode128from unicode
Using Strings With Arrays
FunctionParamsDescriptionExample
Splitexpression, delimiter,
limit, compareParses a delimited string to an arrayarr = Split("A;B;C",";")
Joinsource array, delimiterConverts a one dimensional array to a strings = Join(Arr, ";")
String to Array using Split
You can easily parse a delimited string into an array. You simply use the Split function with the delimiter as parameter. The following code shows an example of using the Split function.
Sub StrToArr()
Dim arr() As String
' Parse string to array
arr = Split("John,Jane,Paul,Sophie", ",")
Dim name As Variant
For Each name In arr
Debug.Print name
Next
End Sub
Output
John
Jane
Paul
Sophie
If you would like to see some real world examples of using Split, you will find them in the post How to Easily Extract From Any String Without Using VBA InStr.
Array to String using Join
If you want to build a string from an array you can do so easily using the Join function. This is essentially a reverse of the Split function. The following code provides an example of using Join
Sub ArrToStr()
Dim Arr(0 To 3) As String
Arr(0) = "John"
Arr(1) = "Jane"
Arr(2) = "Paul"
Arr(3) = "Sophie"
' Build string from array
Dim sNames As String
sNames = Join(Arr, ",")
Debug.Print sNames
End Sub
Output
John,Jane,Paul,Sophie
Formatting a String
FunctionParamsDescriptionExample
Formatexpression, format,
firstdayofweek, firstweekofyearFormats a string Format(0.5, "0.00%")
The Format function is used to format a string based on given instructions. It is mostly used to place a date or number in certain format. The examples below show the most common ways you would format a date.
Sub FormatDate()
Dim s As String
s = "31/12/2015 10:15:45"
' Prints: 31 12 15
Debug.Print Format(s, "DD MM YY")
' Prints: Thu 31 Dec 2015
Debug.Print Format(s, "DDD DD MMM YYYY")
' Prints: Thursday 31 December 2015
Debug.Print Format(s, "DDDD DD MMMM YYYY")
' Prints: 10:15
Debug.Print Format(s, "HH:MM")
' Prints: 10:15:45 AM
Debug.Print Format(s, "HH:MM:SS AM/PM")
End Sub
The following examples are some common ways of formatting numbers
Sub FormatNumbers()
' Prints: 50.00%
Debug.Print Format(0.5, "0.00%")
' Prints: 023.45
Debug.Print Format(23.45, "00#.00")
' Prints: 23,000
Debug.Print Format(23000, "##,000")
' Prints: 023,000
Debug.Print Format(23000, "0##,000")
' Prints: $23.99
Debug.Print Format(23.99, "$#0.00")
End Sub
The Format function is quite a large topic and could use up a full post on it’s own. If you want more information then the MSDN Format Page provides a lot of information.
Helpful Tip for Using Format
A quick way to figure out the formatting to use is by using the cell formatting on an Excel worksheet. For example add a number to a cell. Then right click and format the cell the way you require. When you are happy with the format select Custom from the category listbox on the left. When you select this you can see the format string in the type textbox(see image below). This is the string format you can use in VBA.

Format Cells Dialog
Conclusion
In almost any type of programming, you will spend a great deal of time manipulating strings. This post covers the many different ways you use strings in VBA.
To get the most from use the table at the top to find the type of function you wish to use. Clicking on the left column of this function will bring you to that section.
If you are new to strings in VBA, then I suggest you check out the Read this First section before using any of the functions.
Please feel free to subscribe to my newsletter and get exclusive VBA content that you cannot find here on the blog, as well as free access to my eBook, How to Ace the 21 Most Common Questions in VBA which is full of examples you can use in your own code.
The post The Ultimate Guide to VBA String Functions appeared first on Excel Macro Mastery.
The Ultimate Guide to the VBA String
Which string operation would you like to know more about? Click on the operation of your choice in the table below. This will bring you to that section where you will find in-depth information about the topic along with free code examples you can copy and use right now. Or if you prefer you can scroll down to see the table of contents.
String operationsFunction(s)
Append two or more stringsFormat or "&"
Build a string from an arrayJoin
Compare - normalStrComp or "="
Compare - patternLike
Convert to a stringCStr, Str
Convert string to dateSimple: CDate
Advanced: Format
Convert string to numberSimple: CLng, CInt, CDbl, Val
Advanced: Format
Convert to unicode, wide, narrowStrConv
Convert to upper/lower caseStrConv, UCase, LCase
Extract part of a stringLeft, Right, Mid
Format a stringFormat
Find characters in a stringInStr, InStrRev
Generate a stringString
Get length of a stringLen
Remove blanksLTrim, RTrim, Trim
Replace part of a stringReplace
Reverse a string
StrReverse
Parse string to array Split
Introduction
Using strings is a very important part of VBA. There are many types of manipulation you may wish to do with strings. These include tasks such as
extracting part of a string
comparing strings
converting numbers to a string
formatting a date to include weekday
finding a character in a string
removing blanks
parsing to an array
and so on
The good news is that VBA contains plenty of functions to help you perform these tasks with ease.
This post provides an in-depth guide to using string in VBA. It explains strings in simple terms with clear code examples. I have laid it out so the post can be easily used as a quick reference guide.
If you are going to use strings a lot then I recommend you read the first section as it applies to a lot of the functions. Otherwise you can read in order or just go to the section you require.

© Ra2studio | Dreamstime.com
Read This First!
The following two points are very important when dealing with VBA string functions.
The Original String is not Changed
An important point to remember is that the VBA string functions do not change the original string. They return a new string with the changes the function made. If you want to change the original string you simply assign the result to the original string. See the section Extracting Part of a String for examples of this.
How To Use Compare
Some of the string functions such as StrComp() and Instr() etc. have an optional Compare parameter. This works as follows:
vbTextCompare: Upper and lower case are considered the same
vbBinaryCompare: Upper and lower case are considered different
The following code uses the string comparison function StrComp() to demonstrate the Compare parameter
Sub Comp1()
' Prints 0 : Strings match
Debug.Print StrComp("ABC", "abc", vbTextCompare)
' Prints -1 : Strings do not match
Debug.Print StrComp("ABC", "abc", vbBinaryCompare)
End Sub
You can use the Option Compare setting instead of having to use this parameter each time. Option Compare is set at the top of a Module. Any function that uses the Compare parameter will take this setting as the default. The two ways to use Option Compare are:
1. Option Compare Text: makes vbTextCompare the default Compare argument
Option Compare Text
Sub Comp2()
' Strings match - uses vbCompareText as Compare argument
Debug.Print StrComp("ABC", "abc")
Debug.Print StrComp("DEF", "def")
End Sub
2. Option Compare Binary: Makes vbBinaryCompare the default Compare argument
Option Compare Binary
Sub Comp2()
' Strings do not match - uses vbCompareBinary as Compare argument
Debug.Print StrComp("ABC", "abc")
Debug.Print StrComp("DEF", "def")
End Sub
If Option Compare is not used then the default is Option Compare Binary.
Now that you understand these two important points about string we can go ahead and look at the string functions individually.
Appending Strings

ABC Cube Pile © Aleksandr Atkishkin | Dreamstime.com
You can append strings using the & operator. The following code shows some examples of using it
Sub Append()
Debug.Print "ABC" &amp; "DEF"
Debug.Print "Jane" &amp; " " &amp; "Smith"
Debug.Print "Long " &amp; 22
Debug.Print "Double " &amp; 14.99
Debug.Print "Date " &amp; #12/12/2015#
End Sub
You can see in the example that different types such as dates and number are automatically converted to strings. You may see the operator being used to append strings. The difference is that this operator will only work with string types. If you try to use it with other type you will get an error.
' This will give the error message: "Type Mismatch"
Debug.Print "Long " 22
If you want to do more complex appending of strings then you may wish to use the Format function described below.
Extracting Part of a String
FunctionParamsDescriptionExample
Leftstring, lengthReturn chars from left sideLeft("John Smith",4)
Rightstring, lengthReturn chars from right sideRight("John Smith",5)
Midstring, start, lengthReturn chars from middleMid("John Smith",3,2)
The Left, Right, and Mid functions are used to extract parts of a string. They are very simple functions to use. Left reads characters from the left, Right from the right and Mid from a starting point that you specify.
Sub UseLeftRightMid()
Dim sCustomer As String
sCustomer = "John Thomas Smith"
Debug.Print Left(sCustomer, 4) ' Prints: John
Debug.Print Right(sCustomer, 5) ' Prints: Smith
Debug.Print Left(sCustomer, 11) ' Prints: John Thomas
Debug.Print Right(sCustomer, 12) ' Prints: Thomas Smith
Debug.Print Mid(sCustomer, 1, 4) ' Prints: John
Debug.Print Mid(sCustomer, 6, 6) ' Prints: Thomas
Debug.Print Mid(sCustomer, 13, 5) ' Prints: Smith
End Sub
As mentioned in the previous section, VBA string functions do not change the original string. Instead, they return the result as a new string.
In the next example you can see that the string Fullname was not changed after using the Left function
Sub UsingLeftExample()
Dim Fullname As String
Fullname = "John Smith"
Debug.Print "Firstname is: "; Left(Fullname, 4)
' Original string has not changed
Debug.Print "Fullname is: "; Fullname
End Sub
If you want to change the original string you simply assign it to the return value of the function
Sub ChangingString()
Dim name As String
name = "John Smith"
' Assign return string to the name variable
name = Left(name, 4)
Debug.Print "Name is: "; name
End Sub
Searching Within a String
FunctionParamsDescriptionExample
InStrString1, String2Finds position of stringInStr("John Smith","h")
InStrRevStringCheck, StringMatchFinds position of string from endInStrRev("John Smith","h")
InStr and InStrRev are VBA functions used to search through strings for a substring. If the search string is found then the position(from the start of the check string) of the search string is returned. If the search string is not found then zero is returned. If either string is null then null is returned.
InStr Description of Parameters
InStr() Start[Optional], String1, String2, Compare[Optional]
Start As Long[Optional – Default is 1]: This is a number that specifies the starting search position from the left
String1 As String: The string to search
String2 As String: The string to search for
Compare As vbCompareMethod : See the section on Compare above for more details
InStr Use and Examples
InStr returns the first position in a string where a given substring is found. The following shows some examples of using it
Sub FindSubString()
Dim name As String
name = "John Smith"
' Returns 3 - position of first h
Debug.Print InStr(name, "h")
' Returns 10 - position of first h starting from position 4
Debug.Print InStr(4, name, "h")
' Returns 8
Debug.Print InStr(name, "it")
' Returns 6
Debug.Print InStr(name, "Smith")
' Returns 0 - string "SSS" not found
Debug.Print InStr(name, "SSS")
End Sub
InStrRev Description of Parameters
InStrRev() StringCheck, StringMatch, Start[Optional], Compare[Optional]
StringCheck As String: The string to search
StringMatch: The string to search for
Start As Long[Optional – Default is -1]: This is a number that specifies the starting search position from the right
Compare As vbCompareMethod: See the section on Compare above for more details
InStrRev Use and Examples
The InStrRev function is the same as InStr except that it searches from the end of the string. It’s important to note that the position returned is the position from the start. Therefore if there is only one instance of the search item then both InStr() and InStrRev() will return the same value.
The following code show some examples of using InStrRev
Sub UsingInstrRev()
Dim name As String
name = "John Smith"
' Both Return 1 - position of the only J
Debug.Print InStr(name, "J")
Debug.Print InStrRev(name, "J")
' Returns 10 - second h
Debug.Print InStrRev(name, "h")
' Returns 3 - first h as searches from position 9
Debug.Print InStrRev(name, "h", 9)
' Returns 1
Debug.Print InStrRev(name, "John")
End Sub
Removing Blanks
FunctionParamsDescriptionExample
LTrimstringRemoves spaces from leftLTrim(" John ")
RTrimstringRemoves spaces from rightRTrim(" John ")
TrimstringRemoves Spaces from left and rightTrim(" John ")
The Trim functions are simple functions that remove spaces from either the start or end of a string.
Trim Functions Use and Examples
LTrim removes spaces from the left of a string
RTrim removes spaces from the right of a string
Trim removes spaces from the left and right of a string
Sub TrimStr()
Dim name As String
name = " John Smith "
' Prints "John Smith "
Debug.Print LTrim(name)
' Prints " John Smith"
Debug.Print RTrim(name)
' Prints "John Smith"
Debug.Print Trim(name)
End Sub
Length of a String
FunctionParamsDescriptionExample
LenstringReturns length of stringLen ("John Smith")
Len is a simple function when used with a string. It simply returns the number of characters the string contains. If used with a numeric type such as long it will return the number of bytes.
Sub GetLen()
Dim name As String
name = "John Smith"
' Prints 10
Debug.Print Len("John Smith")
' Prints 3
Debug.Print Len("ABC")
' Prints 4 as Long is 4 bytes in size
Dim total As Long
Debug.Print Len(total)
End Sub
Reversing a String
FunctionParamsDescriptionExample
StrReversestringReverses a stringStrReverse ("John Smith")
StrReverse is another easy-to-use function. It simply returns the given string with the characters reversed.
Sub RevStr()
Dim s As String
s = "Jane Smith"
' Prints: htimS enaJ
Debug.Print StrReverse(s)
End Sub
Comparing Strings
FunctionParamsDescriptionExample
StrCompstring1, string2Compares 2 stringsStrComp ("John", "John")
The function StrComp is used to compare two strings. The following subsections describe how it is used.
Description of Parameters
StrComp() String1, String2, Compare[Optional]
String1 As String: The first string to compare
String2 As String: The second string to compare
Compare As vbCompareMethod : See the section on Compare above for more details
StrComp Return Values
Return ValueDescription
0Strings match
-1string1 less than string2
1string1 greater than string2
Nullif either string is null
Use and Examples
The following are some examples of using the StrComp function
Sub UsingStrComp()
' Returns 0
Debug.Print StrComp("ABC", "ABC", vbTextCompare)
' Returns 1
Debug.Print StrComp("ABCD", "ABC", vbTextCompare)
' Returns -1
Debug.Print StrComp("ABC", "ABCD", vbTextCompare)
' Returns Null
Debug.Print StrComp(Null, "ABCD", vbTextCompare)
End Sub
Compare Strings using Operators
You can also use the equals sign to compare strings. The difference between the equals comparison and the StrComp function are:
The equals sign returns only true or false.
You cannot specify a Compare parameter using the equal sign – it uses the “Option Compare” setting.
The following shows some examples of using equals to compare strings
Option Compare Text
Sub CompareUsingEquals()
' Returns true
Debug.Print "ABC" = "ABC"
' Returns true because "Compare Text" is set above
Debug.Print "ABC" = "abc"
' Returns false
Debug.Print "ABCD" = "ABC"
' Returns false
Debug.Print "ABC" = "ABCD"
' Returns null
Debug.Print Null = "ABCD"
End Sub
The Operator “<>” means “does not equal”. It is essentially the opposite of using the equals sign as the following code shows
Option Compare Text
Sub CompareWithNotEqual()
' Returns false
Debug.Print "ABC" &lt;&gt; "ABC"
' Returns true because "Compare Text" is set above
Debug.Print "ABC" &lt;&gt; "abc"
' Returns true
Debug.Print "ABCD" &lt;&gt; "ABC"
' Returns true
Debug.Print "ABC" &lt;&gt; "ABCD"
' Returns null
Debug.Print Null &lt;&gt; "ABCD"
End Sub
Comparing Strings using Pattern Matching
OperatorParamsDescriptionExample
Likestring, string patternchecks if string has the given pattern"abX" Like "??X"
"54abc5" Like "*abc#"
TokenMeaning
?Any single char
#Any single digit(0-9)
*zero or more characters
[charlist]Any char in the list
[!charlist]Any char not in the char list
Pattern matching is used to determine if a string has a particular pattern of characters. For example, you may want to check that a customer number has 3 digits followed by 3 alphabetic characters or a string has the letters XX followed by any number of characters.
If the string matches the pattern then the return value is true, otherwise it is false.
Pattern matching is similar to the VBA Format function in that there are almost infinite ways to use it. In this section I am going to give some examples that will explain how it works. This should cover the most common uses. If you need more information about pattern matching you can refer to the MSDN Page for the Like operator.
Lets have a look at a basic example using the tokens. Take the following pattern string
[abc][!def]?#X*
Let’s look at how this string works
[abc] a character that is either a,b or c
[!def] a character that is not d,e or f
? any character
# any digit
X the character X
* followed by zero or more characters
Therefore the following string is valid
apY6X
a is one of abc
p is not one of the characters d, e or f
Y is any character
6 is a digit
X is the letter X
The following code examples show the results of various strings with this pattern
Sub Patterns()
' True
Debug.Print 1; "apY6X" Like "[abc][!def]?#X*"
' True - any combination of chars after x is valid
Debug.Print 2; "apY6Xsf34FAD" Like "[abc][!def]?#X*"
' False - char d not in [abc]
Debug.Print 3; "dpY6X" Like "[abc][!def]?#X*"
' False - 2nd char e is in [def]
Debug.Print 4; "aeY6X" Like "[abc][!def]?#X*"
' False - A at position 4 is not a digit
Debug.Print 5; "apYAX" Like "[abc][!def]?#X*"
' False - char at position 5 must be X
Debug.Print 1; "apY6Z" Like "[abc][!def]?#X*"
End Sub
Important Note on VBA Pattern Matching
The Like operator uses either Binary or Text comparison based on the Option Compare setting. Please see the section on Compare above for more details.
Replace Part of a String
FunctionParamsDescriptionExample
Replacestring, find, replace,
start, count, compareReplaces a substring with a substringReplace ("Jon","n","hn")
Replace is used to replace a substring in a string by another substring. It replaces all instances of the substring that are found by default.
Replace Description of Parameters
Replace() Expression, Find, Replace, Start[Optional], Count[Optional], Compare[Optional]
Expression As String: The string to replace chars in
Find As String: The substring to replace in the Expression string
Replace As String: The string to replace the Find substring with
Start As Long[Optional – Default is 1]: The start position in the string
Count As Long[Optional – Default is -1]: The number of substitutions to make. The default -1 means all.
Compare As vbCompareMethod : See the section on Compare above for more details
Use and Examples
The following code shows some examples of using the Replace function
Sub ReplaceExamples()
' Replaces all the ampersands(&amp;) with semi colons(;)
Debug.Print Replace("A&amp;B&amp;C&amp;D&amp;E", "&amp;", ";")
' Replace Smith with Jones
Debug.Print Replace("Peter Smith,Sophia Smith", "Smith", "Jones")
' Replace AX with AB
Debug.Print Replace("ACD AXC BAX", "AX", "AB")
End Sub
Output
A;B;C;D;E
Peter Jones,Sophia Jones
ACD ABC BAB
In the following examples we use the Count optional parameter. Count determines the number of substitutions to make. So for example, setting Count equal to one means that only the first occurrence will be replaced.
Sub ReplaceCount()
' Replaces first ampersand only
Debug.Print Replace("A&amp;B&amp;C&amp;D&amp;E", "&amp;", ";", Count:=1)
' Replaces first three ampersands
Debug.Print Replace("A&amp;B&amp;C&amp;D&amp;E", "&amp;", ";", Count:=3)
End Sub
Output
A;B&C&D&E
A;B;C;D&E
The Start optional parameter allow you to return part of a string. The position you specify using Start is where it starts returning the string from. It will not return any part of the string before this position whether a replace was made or not.
Sub ReplacePartial()
' Use original string from position 4
Debug.Print Replace("A&amp;B&amp;C&amp;D&amp;E", "&amp;", ";", Start:=4)
' Use original string from position 8
Debug.Print Replace("A&amp;B&amp;C&amp;D&amp;E", "&amp;", ";", Start:=8)
' No item replaced but still only returns last 2 characters
Debug.Print Replace("ABCD", "X", "Y", Start:=3)
End Sub
Output
;C;D;E
;E
CD
Sometimes you may only want to replace only upper or lower case letters. You can use the Compare parameter to do this. This is used in a lot of string functions. For more information on this check out the Compare section above.
Sub ReplaceCase()
' Replace capital A's only
Debug.Print Replace("A a A a", "A", "X", Compare:=vbBinaryCompare)
' Replace All A's
Debug.Print Replace("A a A a", "A", "X", Compare:=vbTextCompare)
End Sub
Output
X a X a
X X X X
Multiple Replaces
If you want to replace multiple values in a string you can nest the calls. In the following code we want to replace X and Y with A and B respectively.
Sub ReplaceMulti()
Dim newString As String
' Replace A with X
newString = Replace("ABCD ABDN", "A", "X")
' Now replace B with Y in new string
newString = Replace(newString, "B", "Y")
Debug.Print newString
End Sub
In the next example we will change the above code to perform the same task. We will use the return value of the first replace as the argument for the second replace.
Sub ReplaceMultiNested()
Dim newString As String
' Replace A with X and B with Y
newString = Replace(Replace("ABCD ABDN", "A", "X"), "B", "Y")
Debug.Print newString
End Sub
The result of both of these Subs is
XYCD XYDN
Convert Types to String(Basic)
This section is about converting numbers to a string. A very important point here is that most the time VBA will automatically convert to a string for you. Let’s look at some examples
Sub AutoConverts()
Dim s As String
' Automatically converts number to string
s = 12.99
Debug.Print s
' Automatically converts multiple numbers to string
s = "ABC" &amp; 6 &amp; 12.99
Debug.Print s
' Automatically converts double variable to string
Dim d As Double, l As Long
d = 19.99
l = 55
s = "Values are " &amp; d &amp; " " &amp; l
Debug.Print s
End Sub
When you run the above code you can see that the number were automatically converted to strings. So when you assign a value to a string VBA will look after the conversion for you most of the time. There are conversion functions in VBA and in the following sub sections we will look at the reasons for using them.
Explicit Conversion
FunctionParamsDescriptionExample
CStrexpressionConverts a number variable to a stringCStr ("45.78")
StrnumberConverts a number variable to a stringStr ("45.78")
In certain cases you may want to convert an item to a string without have to place it in a string variable first. In this case you can use the Str or CStr functions. Both take an expression as a function and this can be any type such as long, double, data or boolean.
Let’s look at a simple example. Imagine you are reading a list of values from different types of cells to a collection. You can use the Str/CStr functions to ensure they are all stored as strings. The following code shows an example of this
Sub UseStr()
Dim coll As New Collection
Dim c As Range
' Read cell values to collection
For Each c In Range("A1:A10")
' Use Str to convert cell value to a string
coll.Add Str(c)
Next
' Print out the collection values and type
Dim i As Variant
For Each i In coll
Debug.Print i, TypeName(i)
Next
End Sub
In the above example we use Str to convert the value of the cell to a string. The alternative to this would be to assign the value to a string and then assigning the string to the collection. So you can see that using Str here is much more efficient.
Multi Region
The difference between the Str and CStr functions is that CStr converts based on the region. If your macros will be used in multiple regions then you will need to use CStr for you string conversions.
It is good practise to use CStr when reading values from cells. If your code ends up being used in another region then you will not have to make any changes to make it work correctly.
Convert String to Number- CLng, CDbl, Val etc.
FunctionReturnsExample
CBoolBooleanCBool("True"), CBool("0")
CCurCurrencyCCur("245.567")
CDateDateCDate("1/1/2017")
CDblDoubleCCur("245.567")
CDecDecimalCDec("245.567")
CIntIntegerCInt("45")
CLngLong IntegerCLng("45.78")
CVarVariantCVar("")
The above functions are used to convert strings to various types. If you are assigning to a variable of this type then VBA will do the conversion automatically.
Sub StrToNumeric()
Dim l As Long, d As Double, c As Currency
Dim s As String
s = "45.923239"
l = s
d = s
c = s
Debug.Print "Long is "; l
Debug.Print "Double is "; d
Debug.Print "Currency is "; c
End Sub
Using the conversion types gives more flexibility. It means you can determine the type at runtime. In the following code we set the type based on the sType argument passed to the PrintValue function. As this type can be read from an external source such as a cell, we can set the type at runtime. If we declare a variable as Long then it will always be long when the code runs.
Sub Test()
' Prints 46
PrintValue "45.56", "Long"
' Print 45.56
PrintValue "45.56", ""
End Sub
Sub PrintValue(ByVal s As String, ByVal sType As String)
Dim value
' Set the data type based on a type string
If sType = "Long" Then
value = CLng(s)
Else
value = CDbl(s)
End If
Debug.Print "Type is "; TypeName(value); value
End Sub
If a string is not a valid number(i.e. contains symbols other numeric) then you get a “Type Mismatch” error.
Sub InvalidNumber()
Dim l As Long
' Will give type mismatch error
l = CLng("45A")
End Sub
The Val Function
The value function convert numeric parts of a string to the correct number type.
The Val function converts the first numbers it meets. Once it meets letters in a string it stops. If there are only letters then it returns zero as the value. The following code shows some examples of using Val
Sub UseVal()
' Prints 45
Debug.Print Val("45 New Street")
' Prints 45
Debug.Print Val(" 45 New Street")
' Prints 0
Debug.Print Val("New Street 45")
' Prints 12
Debug.Print Val("12 f 34")
End Sub
The Val function has two disadvantages
1. Not Multi-Region – Val does not recognise international versions of numbers such as using commas instead of decimals. Therefore you should use the above conversion functions when you application will be used in multiple regions.
2. Converts invalid strings to zero – This may be okay in some instances but in most cases it is better if an invalid string raises an error. The application is then aware there is a problem and can act accordingly. The conversion functions such as CLng will raise an error if the string contains non-numeric characters.
Generate a String of items – String Function
FunctionParamsDescriptionExample
Stringnumber, characterConverts a number variable to a stringString (5,"*")
The String function is used to generate a string of repeated characters. The first argument is the number of times to repeat it, the second argument is the character.
Sub GenString()
' Prints: &gt;&gt;&gt;&gt;&gt;
Debug.Print String(5, "&gt;")
' Prints: &gt;&gt;&gt;&gt;&gt;
Debug.Print String(5, 62)
' Prints: (((ABC)))
Debug.Print String(3, "(") &amp; "ABC" &amp; String(3, ")")
End Sub
Convert Case/Unicode – StrConv, UCase, LCase
FunctionParamsDescriptionExample
StrConvstring, conversion, LCIDConverts a StringStrConv("abc",vbUpperCase)
If you want to convert the case of a string to upper or lower you can use the UCase and LCase functions for upper and lower respectively. You can also use the StrConv function with the vbUpperCase or vbLowerCase argument. The following code shows example of using these three functions
Sub ConvCase()
Dim s As String
s = "Mary had a little lamb"
' Upper
Debug.Print UCase(s)
Debug.Print StrConv(s, vbUpperCase)
' Lower
Debug.Print LCase(s)
Debug.Print StrConv(s, vbLowerCase)
' Sets the first letter of each word to upper case
Debug.Print StrConv(s, vbProperCase)
End Sub
Output
MARY HAD A LITTLE LAMB
MARY HAD A LITTLE LAMB
mary had a little lamb
mary had a little lamb
Mary Had A Little Lamb
Other Conversions
As well as case the StrConv can perform other conversions based on the Conversion parameter. The following table shows a list of the different parameter values and what they do. For more information on StrConv check out the MSDN Page.
ConstantValueConverts
vbUpperCase1to upper case
vbLowerCase2to lower case
vbProperCase3first letter of each word to uppercase
vbWide*4from Narrow to Wide
vbNarrow*8from Wide to Narrow
vbKatakana**16from Hiragana to Katakana
vbHiragana32from Katakana to Hiragana
vbUnicode64to unicode
vbFromUnicode128from unicode
Using Strings With Arrays
FunctionParamsDescriptionExample
Splitexpression, delimiter,
limit, compareParses a delimited string to an arrayarr = Split("A;B;C",";")
Joinsource array, delimiterConverts a one dimensional array to a strings = Join(Arr, ";")
String to Array using Split
You can easily parse a delimited string into an array. You simply use the Split function with the delimiter as parameter. The following code shows an example of using the Split function.
Sub StrToArr()
Dim arr() As String
' Parse string to array
arr = Split("John,Jane,Paul,Sophie", ",")
Dim name As Variant
For Each name In arr
Debug.Print name
Next
End Sub
Output
John
Jane
Paul
Sophie
Array to String using Join
If you want to build a string from an array you can do so easily using the Join function. This is essentially a reverse of the Split function. The following code provides an example of using Join
Sub ArrToStr()
Dim Arr(0 To 3) As String
Arr(0) = "John"
Arr(1) = "Jane"
Arr(2) = "Paul"
Arr(3) = "Sophie"
' Build string from array
Dim sNames As String
sNames = Join(Arr, ",")
Debug.Print sNames
End Sub
Output
John,Jane,Paul,Sophie
Formatting a String
FunctionParamsDescriptionExample
Formatexpression, format,
firstdayofweek, firstweekofyearFormats a string Format(0.5, "0.00%")
The Format function is used to format a string based on given instructions. It is mostly used to place a date or number in certain format. The examples below show the most common ways you would format a date.
Sub FormatDate()
Dim s As String
s = "31/12/2015 10:15:45"
' Prints: 31 12 15
Debug.Print Format(s, "DD MM YY")
' Prints: Thu 31 Dec 2015
Debug.Print Format(s, "DDD DD MMM YYYY")
' Prints: Thursday 31 December 2015
Debug.Print Format(s, "DDDD DD MMMM YYYY")
' Prints: 10:15
Debug.Print Format(s, "HH:MM")
' Prints: 10:15:45 AM
Debug.Print Format(s, "HH:MM:SS AM/PM")
End Sub
The following examples are some common ways of formatting numbers
Sub FormatNumbers()
' Prints: 50.00%
Debug.Print Format(0.5, "0.00%")
' Prints: 023.45
Debug.Print Format(23.45, "00#.00")
' Prints: 23,000
Debug.Print Format(23000, "##,000")
' Prints: 023,000
Debug.Print Format(23000, "0##,000")
' Prints: $23.99
Debug.Print Format(23.99, "$#0.00")
End Sub
The Format function is quite a large topic and could use up a full post on it’s own. If you want more information then the MSDN Format Page provides a lot of information.
Helpful Tip for Using Format
A quick way to figure out the formatting to use is by using the cell formatting on an Excel worksheet. For example add a number to a cell. Then right click and format the cell the way you require. When you are happy with the format select Custom from the category listbox on the left. When you select this you can see the format string in the type textbox(see image below). This is the string format you can use in VBA.

Format Cells Dialog
Conclusion
In almost any type of programming, you will spend a great deal of time manipulating strings. This post covers the many different ways you use strings in VBA.
To get the most from use the table at the top to find the type of function you wish to use. Clicking on the left column of this function will bring you to that section.
If you are new to strings in VBA, then I suggest you check out the Read this First section before using any of the functions.
Please feel free to subscribe to my newsletter and get exclusive VBA content that you cannot find here on the blog, as well as free access to my eBook, How to Ace the 21 Most Common Questions in VBA which is full of examples you can use in your own code.
The post The Ultimate Guide to the VBA String appeared first on Excel Macro Mastery.
The Ultimate Guide to Using Strings in Excel VBA
“Music is the melody whose text is the world” – Arthur Schopenhauer
Quick Guide To String Functions
TaskFunction(s)
Appending stringsFormat or "&"
Array to string using JoinJoin
Compare - normalStrComp or "="
Compare - patternLike
Convert to a stringCStr, Str
Convert string to dateSimple: CDate
Advanced: Format
Convert string to numberSimple: CLng, CInt, CDbl, Val
Advanced: Format
Convert unicode, wide, narrowStrConv
Convert upper/lower caseStrConv, UCase, LCase
Extracting part of a stringLeft, Right, Mid
Format a stringFormat
Find characters in a stringInStr, InStrRev
Generate a stringString
Length of a stringLen
Remove blanksLTrim, RTrim, Trim
Replace part of a stringReplace
Reverse a string
StrReverse
String to array using SplitSplit
Introduction
Using strings is a very important part of VBA. There are many types of manipulation you may wish to do with strings. These include tasks such as
extracting part of a string
comparing strings
converting numbers to a string
formatting a date to include weekday
finding a character in a string
removing blanks
parsing to an array
and so on
The good news is that VBA contains plenty of functions to help you perform these tasks with ease.
This post provides an in-depth guide to using string in VBA. It explains strings in simple terms with clear code examples. I have laid it out so the post can be easily used as a quick reference guide.
If you are going to use strings a lot then I recommend you read the first section as it applies to a lot of the functions. Otherwise you can read in order or just go to the section you require.

© Ra2studio | Dreamstime.com
Read This First!
The following two points are very important when dealing with VBA string functions.
The Original String is not Changed
An important point to remember is that the VBA string functions do not change the original string. They return a new string with the changes the function made. If you want to change the original string you simply assign the result to the original string. See the section Extracting Part of a String for examples of this.
How To Use Compare
Some of the string functions such as StrComp() and Instr() etc. have an optional Compare parameter. This works as follows:
vbTextCompare: Upper and lower case are considered the same
vbBinaryCompare: Upper and lower case are considered different
The following code uses the string comparison function StrComp() to demonstrate the Compare parameter
Sub Comp1()
' Prints 0 : Strings match
Debug.Print StrComp("ABC", "abc", vbTextCompare)
' Prints -1 : Strings do not match
Debug.Print StrComp("ABC", "abc", vbBinaryCompare)
End Sub
You can use the Option Compare setting instead of having to use this parameter each time. Option Compare is set at the top of a Module. Any function that uses the Compare parameter will take this setting as the default. The two ways to use Option Compare are:
1. Option Compare Text: makes vbTextCompare the default Compare argument
Option Compare Text
Sub Comp2()
' Strings match - uses vbCompareText as Compare argument
Debug.Print StrComp("ABC", "abc")
Debug.Print StrComp("DEF", "def")
End Sub
2. Option Compare Binary: Makes vbBinaryCompare the default Compare argument
Option Compare Binary
Sub Comp2()
' Strings do not match - uses vbCompareBinary as Compare argument
Debug.Print StrComp("ABC", "abc")
Debug.Print StrComp("DEF", "def")
End Sub
If Option Compare is not used then the default is Option Compare Binary.
Now that you understand these two important points about string we can go ahead and look at the string functions individually.
Appending Strings

ABC Cube Pile © Aleksandr Atkishkin | Dreamstime.com
You can append strings using the & operator. The following code shows some examples of using it
Sub Append()
Debug.Print "ABC" & "DEF"
Debug.Print "Jane" & " " & "Smith"
Debug.Print "Long " & 22
Debug.Print "Double " & 14.99
Debug.Print "Date " & #12/12/2015#
End Sub
You can see in the example that different types such as dates and number are automatically converted to strings. You may see the + operator being used to append strings. The difference is that this operator will only work with string types. If you try to use it with other type you will get an error.
' This will give the error message: "Type Mismatch"
Debug.Print "Long " + 22
If you want to do more complex appending of strings then you may wish to use the Format function described below.
Extracting Part of a String
FunctionParamsDescriptionExample
Leftstring, lengthReturn chars from left sideLeft("John Smith",4)
Rightstring, lengthReturn chars from right sideRight("John Smith",5)
Midstring, start, lengthReturn chars from middleMid("John Smith",3,2)
The Left, Right, and Mid functions are used to extract parts of a string. They are very simple functions to use. Left reads characters from the left, Right from the right and Mid from a starting point that you specify.
Sub UseLeftRightMid()
Dim sCustomer As String
sCustomer = "John Thomas Smith"
Debug.Print Left(sCustomer, 4) ' Prints: John
Debug.Print Right(sCustomer, 5) ' Prints: Smith
Debug.Print Left(sCustomer, 11) ' Prints: John Thomas
Debug.Print Right(sCustomer, 12) ' Prints: Thomas Smith
Debug.Print Mid(sCustomer, 1, 4) ' Prints: John
Debug.Print Mid(sCustomer, 6, 6) ' Prints: Thomas
Debug.Print Mid(sCustomer, 13, 5) ' Prints: Smith
End Sub
As mentioned in the previous section, VBA string functions do not change the original string. Instead, they return the result as a new string.
In the next example you can see that the string Fullname was not changed after using the Left function
Sub UsingLeftExample()
Dim Fullname As String
Fullname = "John Smith"
Debug.Print "Firstname is: "; Left(Fullname, 4)
' Original string has not changed
Debug.Print "Fullname is: "; Fullname
End Sub
If you want to change the original string you simply assign it to the return value of the function
Sub ChangingString()
Dim name As String
name = "John Smith"
' Assign return string to the name variable
name = Left(name, 4)
Debug.Print "Name is: "; name
End Sub
Searching Within a String
FunctionParamsDescriptionExample
InStrString1, String2Finds position of stringInStr("John Smith","h")
InStrRevStringCheck, StringMatchFinds position of string from endInStrRev("John Smith","h")
InStr and InStrRev are VBA functions used to search through strings for a substring. If the search string is found then the position(from the start of the check string) of the search string is returned. If the search string is not found then zero is returned. If either string is null then null is returned.
InStr Description of Parameters
InStr() Start[Optional], String1, String2, Compare[Optional]
Start As Long[Optional – Default is 1]: This is a number that specifies the starting search position from the left
String1 As String: The string to search
String2 As String: The string to search for
Compare As vbCompareMethod : See the section on Compare above for more details
InStr Use and Examples
InStr returns the first position in a string where a given substring is found. The following shows some examples of using it
Sub FindSubString()
Dim name As String
name = "John Smith"
' Returns 3 - position of first h
Debug.Print InStr(name, "h")
' Returns 10 - position of first h starting from position 4
Debug.Print InStr(4, name, "h")
' Returns 8
Debug.Print InStr(name, "it")
' Returns 6
Debug.Print InStr(name, "Smith")
' Returns 0 - string "SSS" not found
Debug.Print InStr(name, "SSS")
End Sub
InStrRev Description of Parameters
InStrRev() StringCheck, StringMatch, Start[Optional], Compare[Optional]
StringCheck As String: The string to search
StringMatch: The string to search for
Start As Long[Optional – Default is -1]: This is a number that specifies the starting search position from the right
Compare As vbCompareMethod: See the section on Compare above for more details
InStrRev Use and Examples
The InStrRev function is the same as InStr except that it searches from the end of the string. It’s important to note that the position returned is the position from the start. Therefore if there is only one instance of the search item then both InStr() and InStrRev() will return the same value.
The following code show some examples of using InStrRev
Sub UsingInstrRev()
Dim name As String
name = "John Smith"
' Both Return 1 - position of the only J
Debug.Print InStr(name, "J")
Debug.Print InStrRev(name, "J")
' Returns 10 - second h
Debug.Print InStrRev(name, "h")
' Returns 3 - first h as searches from position 9
Debug.Print InStrRev(name, "h", 9)
' Returns 1
Debug.Print InStrRev(name, "John")
End Sub
Removing Blanks
FunctionParamsDescriptionExample
LTrimstringRemoves spaces from leftLTrim(" John ")
RTrimstringRemoves spaces from rightRTrim(" John ")
TrimstringRemoves Spaces from left and rightTrim(" John ")
The Trim functions are simple functions that remove spaces from either the start or end of a string.
Trim Functions Use and Examples
LTrim removes spaces from the left of a string
RTrim removes spaces from the right of a string
Trim removes spaces from the left and right of a string
Sub TrimStr()
Dim name As String
name = " John Smith "
' Prints "John Smith "
Debug.Print LTrim(name)
' Prints " John Smith"
Debug.Print RTrim(name)
' Prints "John Smith"
Debug.Print Trim(name)
End Sub
Length of a String
FunctionParamsDescriptionExample
LenstringReturns length of stringLen ("John Smith")
Len is a simple function when used with a string. It simply returns the number of characters the string contains. If used with a numeric type such as long it will return the number of bytes.
Sub GetLen()
Dim name As String
name = "John Smith"
' Prints 10
Debug.Print Len("John Smith")
' Prints 3
Debug.Print Len("ABC")
' Prints 4 as Long is 4 bytes in size
Dim total As Long
Debug.Print Len(total)
End Sub
Reversing a String
FunctionParamsDescriptionExample
StrReversestringReverses a stringStrReverse ("John Smith")
StrReverse is another easy-to-use function. It simply returns the given string with the characters reversed.
Sub RevStr()
Dim s As String
s = "Jane Smith"
' Prints: htimS enaJ
Debug.Print StrReverse(s)
End Sub
Comparing Strings
FunctionParamsDescriptionExample
StrCompstring1, string2Compares 2 stringsStrComp ("John", "John")
The function StrComp is used to compare two strings. The following subsections describe how it is used.
Description of Parameters
StrComp() String1, String2, Compare[Optional]
String1 As String: The first string to compare
String2 As String: The second string to compare
Compare As vbCompareMethod : See the section on Compare above for more details
StrComp Return Values
Return ValueDescription
0Strings match
-1string1 less than string2
1string1 greater than string2
Nullif either string is null
Use and Examples
The following are some examples of using the StrComp function
Sub UsingStrComp()
' Returns 0
Debug.Print StrComp("ABC", "ABC", vbTextCompare)
' Returns 1
Debug.Print StrComp("ABCD", "ABC", vbTextCompare)
' Returns -1
Debug.Print StrComp("ABC", "ABCD", vbTextCompare)
' Returns Null
Debug.Print StrComp(Null, "ABCD", vbTextCompare)
End Sub
Compare Strings using Operators
You can also use the equals sign to compare strings. The difference between the equals comparison and the StrComp function are:
The equals sign returns only true or false.
You cannot specify a Compare parameter using the equal sign – it uses the “Option Compare” setting.
The following shows some examples of using equals to compare strings
Option Compare Text
Sub CompareUsingEquals()
' Returns true
Debug.Print "ABC" = "ABC"
' Returns true because "Compare Text" is set above
Debug.Print "ABC" = "abc"
' Returns false
Debug.Print "ABCD" = "ABC"
' Returns false
Debug.Print "ABC" = "ABCD"
' Returns null
Debug.Print Null = "ABCD"
End Sub
The Operator “<>” means “does not equal”. It is essentially the opposite of using the equals sign as the following code shows
Option Compare Text
Sub CompareWithNotEqual()
' Returns false
Debug.Print "ABC" <> "ABC"
' Returns true because "Compare Text" is set above
Debug.Print "ABC" <> "abc"
' Returns true
Debug.Print "ABCD" <> "ABC"
' Returns true
Debug.Print "ABC" <> "ABCD"
' Returns null
Debug.Print Null <> "ABCD"
End Sub
Comparing Strings using Pattern Matching
OperatorParamsDescriptionExample
Likestring, string patternchecks if string has the given pattern"abX" Like "??X"
"54abc5" Like "*abc#"
TokenMeaning
?Any single char
#Any single digit(0-9)
*zero or more characters
[charlist]Any char in the list
[!charlist]Any char not in the char list
Pattern matching is used to determine if a string has a particular pattern of characters. For example, you may want to check that a customer number has 3 digits followed by 3 alphabetic characters or a string has the letters XX followed by any number of characters.
If the string matches the pattern then the return value is true, otherwise it is false.
Pattern matching is similar to the VBA Format function in that there are almost infinite ways to use it. In this section I am going to give some examples that will explain how it works. This should cover the most common uses. If you need more information about pattern matching you can refer to the MSDN Page for the Like operator.
Lets have a look at a basic example using the tokens. Take the following pattern string
[abc][!def]?#X*
Let’s look at how this string works
[abc] a character that is either a,b or c
[!def] a character that is not d,e or f
? any character
# any digit
X the character X
* followed by zero or more characters
Therefore the following string is valid
apY6X
a is one of abc
p is not one of the characters d, e or f
Y is any character
6 is a digit
X is the letter X
The following code examples show the results of various strings with this pattern
Sub Patterns()
' True
Debug.Print 1; "apY6X" Like "[abc][!def]?#X*"
' True - any combination of chars after x is valid
Debug.Print 2; "apY6Xsf34FAD" Like "[abc][!def]?#X*"
' False - char d not in [abc]
Debug.Print 3; "dpY6X" Like "[abc][!def]?#X*"
' False - 2nd char e is in [def]
Debug.Print 4; "aeY6X" Like "[abc][!def]?#X*"
' False - A at position 4 is not a digit
Debug.Print 5; "apYAX" Like "[abc][!def]?#X*"
' False - char at position 5 must be X
Debug.Print 1; "apY6Z" Like "[abc][!def]?#X*"
End Sub
Important Note on VBA Pattern Matching
The Like operator uses either Binary or Text comparison based on the Option Compare setting. Please see the section on Compare above for more details
Replace Part of a String
FunctionParamsDescriptionExample
Replacestring, find, replace,
start, count, compareReplaces a substring with a substringReplace ("Jon","n","hn")
Replace is used to replace a substring in a string by another substring. It replaces all instances of the substring that are found by default.
Replace Description of Parameters
Replace() Expression, Find, Replace, Start[Optional], Count[Optional], Compare[Optional]
Expression As String: The string to replace chars in
Find As String: The substring to replace in the Expression string
Replace As String: The string to replace the Find substring with
Start As Long[Optional – Default is 1]: The start position in the string
Count As Long[Optional – Default is -1]: The number of substitutions to make. The default -1 means all.
Compare As vbCompareMethod : See the section on Compare above for more details
Use and Examples
The following code shows some examples of using the Replace function
Sub ReplaceExamples()
' Replaces all the ampersands(&) with semi colons(;)
Debug.Print Replace("A&B&C&D&E", "&", ";")
' Replace Smith with Jones
Debug.Print Replace("Peter Smith,Sophia Smith", "Smith", "Jones")
' Replace AX with AB
Debug.Print Replace("ACD AXC BAX", "AX", "AB")
End Sub
Output
A;B;C;D;E
Peter Jones,Sophia Jones
ACD ABC BAB
In the following examples we use the Count optional parameter. Count determines the number of substitutions to make. So for example, setting Count equal to one means that only the first occurrence will be replaced.
Sub ReplaceCount()
' Replaces first ampersand only
Debug.Print Replace("A&B&C&D&E", "&", ";", Count:=1)
' Replaces first three ampersands
Debug.Print Replace("A&B&C&D&E", "&", ";", Count:=3)
End Sub
Output
A;B&C&D&E
A;B;C;D&E
The Start optional parameter allow you to return part of a string. The position you specify using Start is where it starts returning the string from. It will not return any part of the string before this position whether a replace was made or not.
Sub ReplacePartial()
' Use original string from position 4
Debug.Print Replace("A&B&C&D&E", "&", ";", Start:=4)
' Use original string from position 8
Debug.Print Replace("A&B&C&D&E", "&", ";", Start:=8)
' No item replaced but still only returns last 2 characters
Debug.Print Replace("ABCD", "X", "Y", Start:=3)
End Sub
Output
;C;D;E
;E
CD
Sometimes you may only want to replace only upper or lower case letters. You can use the Compare parameter to do this. This is used in a lot of string functions. For more information on this check out the Compare section above.
Sub ReplaceCase()
' Replace capital A's only
Debug.Print Replace("A a A a", "A", "X", Compare:=vbBinaryCompare)
' Replace All A's
Debug.Print Replace("A a A a", "A", "X", Compare:=vbTextCompare)
End Sub
Output
X a X a
X X X X
Multiple Replaces
If you want to replace multiple values in a string you can nest the calls. In the following code we want to replace X and Y with A and B respectively.
Sub ReplaceMulti()
Dim newString As String
' Replace A with X
newString = Replace("ABCD ABDN", "A", "X")
' Now replace B with Y in new string
newString = Replace(newString, "B", "Y")
Debug.Print newString
End Sub
In the next example we will change the above code to perform the same task. We will use the return value of the first replace as the argument for the second replace.
Sub ReplaceMultiNested()
Dim newString As String
' Replace A with X and B with Y
newString = Replace(Replace("ABCD ABDN", "A", "X"), "B", "Y")
Debug.Print newString
End Sub
The result of both of these Subs is
XYCD XYDN
Convert Types to String(Basic)
This section is about converting numbers to a string. A very important point here is that most the time VBA will automatically convert to a string for you. Let’s look at some examples
Sub AutoConverts()
Dim s As String
' Automatically converts number to string
s = 12.99
Debug.Print s
' Automatically converts multiple numbers to string
s = "ABC" & 6 & 12.99
Debug.Print s
' Automatically converts double variable to string
Dim d As Double, l As Long
d = 19.99
l = 55
s = "Values are " & d & " " & l
Debug.Print s
End Sub
When you run the above code you can see that the number were automatically converted to strings. So when you assign a value to a string VBA will look after the conversion for you most of the time. There are conversion functions in VBA and in the following sub sections we will look at the reasons for using them.
Explicit Conversion
FunctionParamsDescriptionExample
CStrexpressionConverts a number variable to a stringCStr ("45.78")
StrnumberConverts a number variable to a stringStr ("45.78")
In certain cases you may want to convert an item to a string without have to place it in a string variable first. In this case you can use the Str or CStr functions. Both take an expression as a function and this can be any type such as long, double, data or boolean.
Let’s look at a simple example. Imagine you are reading a list of values from different types of cells to a collection. You can use the Str/CStr functions to ensure they are all stored as strings. The following code shows an example of this
Sub UseStr()
Dim coll As New Collection
Dim c As Range
' Read cell values to collection
For Each c In Range("A1:A10")
' Use Str to convert cell value to a string
coll.Add Str(c)
Next
' Print out the collection values and type
Dim i As Variant
For Each i In coll
Debug.Print i, TypeName(i)
Next
End Sub
In the above example we use Str to convert the value of the cell to a string. The alternative to this would be to assign the value to a string and then assigning the string to the collection. So you can see that using Str here is much more efficient.
Multi Region
The difference between the Str and CStr functions is that CStr converts based on the region. If your macros will be used in multiple regions then you will need to use CStr for you string conversions.
It is good practise to use CStr when reading values from cells. If your code ends up being used in another region then you will not have to make any changes to make it work correctly.
Convert String to Number- CLng, CDbl, Val etc.
FunctionReturnsExample
CBoolBooleanCBool("True"), CBool("0")
CCurCurrencyCCur("245.567")
CDateDateCDate("1/1/2017")
CDblDoubleCCur("245.567")
CDecDecimalCDec("245.567")
CIntIntegerCInt("45")
CLngLong IntegerCLng("45.78")
CVarVariantCVar("")
The above functions are used to convert strings to various types. If you are assigning to a variable of this type then VBA will do the conversion automatically.
Sub StrToNumeric()
Dim l As Long, d As Double, c As Currency
Dim s As String
s = "45.923239"
l = s
d = s
c = s
Debug.Print "Long is "; l
Debug.Print "Double is "; d
Debug.Print "Currency is "; c
End Sub
Using the conversion types gives more flexibility. It means you can determine the type at runtime. In the following code we set the type based on the sType argument passed to the PrintValue function. As this type can be read from an external source such as a cell, we can set the type at runtime. If we declare a variable as Long then it will always be long when the code runs.
Sub Test()
' Prints 46
PrintValue "45.56", "Long"
' Print 45.56
PrintValue "45.56", ""
End Sub
Sub PrintValue(ByVal s As String, ByVal sType As String)
Dim value
' Set the data type based on a type string
If sType = "Long" Then
value = CLng(s)
Else
value = CDbl(s)
End If
Debug.Print "Type is "; TypeName(value); value
End Sub
If a string is not a valid number(i.e. contains symbols other numeric) then you get a “Type Mismatch” error.
Sub InvalidNumber()
Dim l As Long
' Will give type mismatch error
l = CLng("45A")
End Sub
The Val Function
The value function convert numeric parts of a string to the correct number type.
The Val function converts the first numbers it meets. Once it meets letters in a string it stops. If there are only letters then it returns zero as the value. The following code shows some examples of using Val
Sub UseVal()
' Prints 45
Debug.Print Val("45 New Street")
' Prints 45
Debug.Print Val(" 45 New Street")
' Prints 0
Debug.Print Val("New Street 45")
' Prints 12
Debug.Print Val("12 f 34")
End Sub
The Val function has two disadvantages
1. Not Multi-Region – Val does not recognise international versions of numbers such as using commas instead of decimals. Therefore you should use the above conversion functions when you application will be used in multiple regions.
2. Converts invalid strings to zero – This may be okay in some instances but in most cases it is better if an invalid string raises an error. The application is then aware there is a problem and can act accordingly. The conversion functions such as CLng will raise an error if the string contains non-numeric characters.
Generate a String of items – String Function
FunctionParamsDescriptionExample
Stringnumber, characterConverts a number variable to a stringString (5,"*")
The String function is used to generate a string of repeated characters. The first argument is the number of times to repeat it, the second argument is the character.
Sub GenString()
' Prints: >>>>>
Debug.Print String(5, ">")
' Prints: >>>>>
Debug.Print String(5, 62)
' Prints: (((ABC)))
Debug.Print String(3, "(") & "ABC" & String(3, ")")
End Sub
Convert Case/Unicode – StrConv, UCase, LCase
FunctionParamsDescriptionExample
StrConvstring, conversion, LCIDConverts a StringStrConv("abc",vbUpperCase)
If you want to convert the case of a string to upper or lower you can use the UCase and LCase functions for upper and lower respectively. You can also use the StrConv function with the vbUpperCase or vbLowerCase argument. The following code shows example of using these three functions
Sub ConvCase()
Dim s As String
s = "Mary had a little lamb"
' Upper
Debug.Print UCase(s)
Debug.Print StrConv(s, vbUpperCase)
' Lower
Debug.Print LCase(s)
Debug.Print StrConv(s, vbLowerCase)
' Sets the first letter of each word to upper case
Debug.Print StrConv(s, vbProperCase)
End Sub
Output
MARY HAD A LITTLE LAMB
MARY HAD A LITTLE LAMB
mary had a little lamb
mary had a little lamb
Mary Had A Little Lamb
Other Conversions
As well as case the StrConv can perform other conversions based on the Conversion parameter. The following table shows a list of the different parameter values and what they do. For more information on StrConv check out the MSDN Page.
ConstantValueConverts
vbUpperCase1to upper case
vbLowerCase2to lower case
vbProperCase3first letter of each word to uppercase
vbWide*4from Narrow to Wide
vbNarrow*8from Wide to Narrow
vbKatakana**16from Hiragana to Katakana
vbHiragana32from Katakana to Hiragana
vbUnicode64to unicode
vbFromUnicode128from unicode
Using Strings With Arrays
FunctionParamsDescriptionExample
Splitexpression, delimiter,
limit, compareParses a delimited string to an arrayarr = Split("A;B;C",";")
Joinsource array, delimiterConverts a one dimensional array to a strings = Join(Arr, ";")
String to Array using Split
You can easily parse a delimited string into an array. You simply use the Split function with the delimiter as parameter. The following code shows an example of using the Split function.
Sub StrToArr()
Dim arr() As String
' Parse string to array
arr = Split("John,Jane,Paul,Sophie", ",")
Dim name As Variant
For Each name In arr
Debug.Print name
Next
End Sub
Output
John
Jane
Paul
Sophie
Array to String using Join
If you want to build a string from an array you can do so easily using the Join function. This is essentially a reverse of the Split function. The following code provides an example of using Join
Sub ArrToStr()
Dim Arr(0 To 3) As String
Arr(0) = "John"
Arr(1) = "Jane"
Arr(2) = "Paul"
Arr(3) = "Sophie"
' Build string from array
Dim sNames As String
sNames = Join(Arr, ",")
Debug.Print sNames
End Sub
Output
John,Jane,Paul,Sophie
Formatting a String
FunctionParamsDescriptionExample
Formatexpression, format,
firstdayofweek, firstweekofyearFormats a string Format(0.5, "0.00%")
The Format function is used to format a string based on given instructions. It is mostly used to place a date or number in certain format. The examples below show the most common ways you would format a date.
Sub FormatDate()
Dim s As String
s = "31/12/2015 10:15:45"
' Prints: 31 12 15
Debug.Print Format(s, "DD MM YY")
' Prints: Thu 31 Dec 2015
Debug.Print Format(s, "DDD DD MMM YYYY")
' Prints: Thursday 31 December 2015
Debug.Print Format(s, "DDDD DD MMMM YYYY")
' Prints: 10:15
Debug.Print Format(s, "HH:MM")
' Prints: 10:15:45 AM
Debug.Print Format(s, "HH:MM:SS AM/PM")
End Sub
The following examples are some common ways of formatting numbers
Sub FormatNumbers()
' Prints: 50.00%
Debug.Print Format(0.5, "0.00%")
' Prints: 023.45
Debug.Print Format(23.45, "00#.00")
' Prints: 23,000
Debug.Print Format(23000, "##,000")
' Prints: 023,000
Debug.Print Format(23000, "0##,000")
' Prints: $23.99
Debug.Print Format(23.99, "$#0.00")
End Sub
The Format function is quite a large topic and could use up a full post on it’s own. If you want more information then the MSDN Format Page provides a lot of information.
Helpful Tip for Using Format
A quick way to figure out the formatting to use is by using the cell formatting on an Excel worksheet. For example add a number to a cell. Then right click and format the cell the way you require. When you are happy with the format select Custom from the category listbox on the left. When you select this you can see the format string in the type textbox(see image below). This is the string format you can use in VBA.

Format Cells Dialog
Conclusion
If you found this post useful then you’ll definitely enjoy my free eBook How to Ace 21 Most Common Questions in VBA. If you want to check out more posts on this blog then the complete list by category is available here.
April 23, 2015
The Ultimate Guide To Collections in Excel VBA
“I’m not a builder of buildings, I’m a builder of collections” – Leonard Lauder
The table below will show you how to use collections in VBA. For a simple and complete guide to Collections in VBA check out the rest of this post.

A Quick Guide to VBA Collections
Introduction
Collections are a very important part of VBA. If you have used the language for any length of time then you will have used Collections. The most common ones are the Workbooks, Worksheets, Range and Cells collections. The following code shows some examples of using the VBA Workbooks collection
' Workbooks is a collection of all open workbooks
' Count is the number of workbooks in the collection
Debug.Print Workbooks.Count
' Print the full name of the workbook called Example.xlsm
Debug.Print Workbooks("Example.xlsm").FullName
' Print the full name of the workbook that was opened second
Debug.Print Workbooks(2).FullName
Collections are similar to arrays so it is important to understand what they are and how the differ to arrays.
What is a Collection?
[image error]
© Vlaskoff | Dreamstime.com. A Collection of the old Soviet cars
Collections and arrays are both used to group variables. They both store a set of similar items e.g. a list of student marks or country names. Using a collection or array allows you to quickly and easily manipulate a large number of items.
In my post on arrays, I explained in simple terms what arrays are and why they are so useful. I will briefly recap this information here.
If you were storing the marks of one student then you can easily do this using a single variable
Dim mark As Long
mark = sheetMarks.Range("A1")
However most of the time you will have more than one student to deal with. Imagine you want to store the marks of 100 students. If you didn’t use collections or arrays you would need to create a hundred variables – one variable to store the mark for each student.
Another problem is that you have to use these variables individually. If you want to store 100 marks then you need a line of code each time you want to store a value to a variable.
' Declare a variable for each mark
Dim mark1 As Long
Dim mark2 As Long
.
.
.
Dim mark100 As Long
' Store the marks from the worksheet in a variable
mark1 = sheetMarks.Range("A1")
mark2 = sheetMarks.Range("A2")
.
.
.
mark100 = sheetMarks.Range("A100")
As you can see in the above example, writing code like this would mean hundreds of lines of repetitive code. When you use a collection or array you only need to declare one variable. Using a loop with a collection or arrays means you only need one line for add or reading values.
If we rewrite the above example using a collection then we only need a few lines of code
' Create collection
Dim collMarks As New Collection
' Read 100 values to collection
Dim c As Range
For Each c In Sheet1.Range("A1:A100")
' This line is used to add all the values
collMarks.Add c.Value
Next
Collections Vs Arrays?
We have looked at what collections and arrays have in common. So what is the difference and why use one over the other?
The main difference is that with an array you normally set the size once. This means that you know the size before you start adding elements. Let me explain this with an example.
Example: Where an Array is Better
Imagine you have a worksheet of student marks with one student per row

Student Marks
You want to store information about each student. In this example you can easily count the number of rows to get the number of students. In other words you know the number of items in advance.
' Get last row - this is the number of students
Dim lStudentCount As Long
lStudentCount = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
' Create array of correct size
Dim arr() As Long
ReDim arr(1 To lStudentCount)
In the example code you can see that we get the number of students by counting the rows. We can then use this to create an array of the correct size.
Let us now look at a second example where we don’t know the number of items in advance
Example Where a Collection is Better
In this example we have the same student worksheet but this time we only want the of students with a given criteria. For example only the students from the USA or England that study Maths or History. In other words you will not how to select a student until you read their details from the worksheet.
Imagine also that students can be added or removed from the list as the application runs.
So in this example the number of students is not fixed and changes a lot. Here you do not know the number of students in advance. Therefore you do not know what size array to create.
You could create an array of the biggest possible size. The problem is you would have a lot of empty slots and would have to add code to deal with these. If you read 50 students from a max of 1000 then you would have 950 unused array slots.
You could also resize the array for each item as it is added. This is very inefficient and quite messy to do. So for this example using a collection would be better.
' Declare
Dim coll As New Collection
' Add item - VBA looks after resizing
coll.Add "Apple"
coll.Add "Pear"
' remove item - VBA looks after resizing
coll.Remove 1
When you add or remove an item to a collection VBA does all the resizing for you. You don’t have to specify the size or allocate new spaces. VBA does it under the hood. All you have to do is add an item or remove it.
Another Advantage of Collections
Collections are much easier to use than arrays especially if you are new to programming. Most of the time you do three things with collections:
Create the collection
Add some items
Read through the items
So if you are not dealing with a larger number of items then using a Collection can be much neater to use.
A Disadvantage of Collections
Collections are read-only.You can add or remove an item but you cannot change the value of the item. If you are going to be changing the values in a group of items then you will need to use an array.
Now that we know when and why to use a collection let’s look at how to use one.
How to Create a Collection
You can declare and create in one line as the following code does
' Declare and create
Dim coll As New Collection
As you can see you don’t need to specify the size. Once your collection has been created you can easily add items to it.
You can also declare and then create the collection if and when you need it.
' Declare
Dim coll As Collection
' Create Collection
Set coll = New Collection
Minor Difference Between These Methods
The difference between these methods is that for the first one the collection is always created. For the second method the collection is only created when the Set line is reached. So you could set the code to only create the collection if a certain condition was met
' Declare
Dim coll As Collection
' Create Collection if a file is found
If filefound = True Then
Set coll = New Collection
Endif
The advantage to using this method is minimal. Allocating memory was important back in the 1990’s when computer memory was limited. Unless you are creating a huge number of collections on a slow PC you will never notice any benefit.
Use Set means the collection will behave differently than when you set the collection to nothing. The next section explains this.
Removing All items from a Collection
To remove all items from a collection you can simply set it to nothing.
Set Coll = Nothing
An important point to understand here is that what this does depends on how you created the collection. As we saw you can create a Collection by declaring using New or by using Set and New. Let’s look at both types
Declaring Using New
If you set this collection to nothing then it will be set to the state where the “object is not set”. When you add a new item VBA automatically sets the Collection variable to a valid collection.
In other words if you set the collection to nothing it will empty all the items. If you then add an item to the collection you will now have a collection with one item. This makes it simple to empty a collection.
The following code demonstrates this.
Sub EmptyColl()
' Create collection and add items
Dim coll As New Collection
' add items here
' Empty collection
Set coll = Nothing
' Add item
coll.Add "Pear"
End Sub
A subtle point to emphasize here is that when you set the collection to Nothing it is not actually set to nothing. Therefore if you try to compare it with being it will not work.
Using Set and New
When you use Set to create a collection you must create the collection again if you set it to Nothing. In the following code after setting to nothing you must then set using new again. If you don’t do this you will get the error: “Object Variable or With block variable not set”.
Sub EmptyCollSet()
' Create collection
Dim coll As Collection
Set coll = New Collection
' Add items here
' Empty collection
Set coll = Nothing
' SET TO NEW BEFORE USING
Set coll = New Collection
' Add item
coll.Add "Pear"
End Sub
Remove All – An Alternative Method
The following method will also remove all the elements of a collection but is a slower way to do it. The advantage is that is will work no matter which way you create the collection.
Sub RemoveAll(ByRef coll As Collection)
Dim i As Long
For i = coll.Count To 1 Step -1
coll.Remove i
Next i
End Sub
Adding items to a Collection
It is simple to add items to a collection. You use the add property followed by the value you wish to add.
collFruit.Add "Apple"
collFruit.Add "Pear"
You can have any basic type in a collection such as a Double
collTotals.Add 45.67
collTotals.Add 34.67
When you add items in this manner they are added to the next available index. In the fruit example, Apple is added to position 1 and Pear to position 2.
Before and After
You can use the Before or After parameters to specify where you want to place the item in the collection. Note you cannot use both of these arguments at the same time.
collFruit.Add "Apple"
collFruit.Add "Pear"
' Add lemon before first item
collFruit.Add "Lemon" Before:=1
After this code the collection is in the order
1. Lemon
2. Apple
3. Pear
collFruit.Add "Apple"
collFruit.Add "Pear"
' Add lemon after first item
collFruit.Add "Lemon" After:=1
After this code the collection is in the order
1. Apple
2. Lemon
3. Pear
Accessing Items of a Collection
To Access the items of a collection you simply use the index. As we saw the index is the position of the item in the collection based on the order they were added. The order can also be set using the Before or After parameter.
Sub access()
Dim coll As New Collection
coll.Add "Apple"
coll.Add "Pear"
' Will print Apple
Debug.Print coll(1)
' Add orange first
coll.Add "Orange", Before:=1
' Will print Orange
Debug.Print coll(1)
' Will print Apple as it is now in position 2
Debug.Print coll(2)
End Sub
You can also use the Item Property to access an item in the collection. It is the default method of the collection so the followling lines of code are equivalent
Debug.Print coll(1)
Debug.Print coll.Item(1)
Items in a collection are Read Only
This is a very important point. You cannot change the value of an item in a collection. When you access an item from a collection it is read only. If you try to write to a collection item you will get an error. The following code produces an “object required” error
Sub WriteValue()
Dim coll As New Collection
coll.Add "Apple"
' This line causes an ERRROR
coll(1) = "Pear"
End Sub
Adding different types
You can also add different types of items to a collection.
collFruit.Add "Apple"
collFruit.Add 45
collFruit.Add #12/12/2017#
This is seldom needed. In VBA the Sheets collections contains sheets of type Worksheet and of type Chart. (To create a Chart sheet simple right click on any Chart, select Move and select the radio button for New sheet).
The following code displays the type and name of all the sheets in the current workbook. Note to access different type you need the For Each variable to be a variant or you will get an error.
Sub ListSheets()
Dim sh As Variant
For Each sh In ThisWorkbook.Sheets
' Display type and name of sheet
Debug.Print TypeName(sh), sh.Name
Next
End Sub
When you access different items the For Each variable must be a variant. If it’s not you will get an error when you access a different type than you declared. If we declared sh as a worksheet in the above example it would give an error when we try to access a sheet of type Chart.
It is rare that you would need a collection of different types but as you can see sometimes it can be useful.
Adding Items Using a Key
You can also add items using a key as the next example shows
collMark.Add Item:=45, Key:="Bill"
Debug.Print "Bill's Marks are: ",collMark("Bill")
I included the parameter names to make the above example clear. However you don’t need to do this. Just remember the key is the second parameter and must be a unique string.
The following code shows a second example of using keys
Sub UseKey()
Dim collMark As New Collection
collMark.Add 45, "Bill"
collMark.Add 67, "Hank"
collMark.Add 12, "Laura"
collMark.Add 89, "Betty"
' Print Betty's marks
Debug.Print collMark("Betty")
' Print Bill's marks
Debug.Print collMark("Bill")
End Sub
Using keys is has three advantages:
If the order changes your code will still access the correct item
You can directly access the item without reading through the entire collection
It can make you code more readable
In the VBA Workbooks collection it is much better to access the workbook by the key(name) the by the index. The order is dependent on when they were opened and so is quite random.
Sub UseAWorkbook()
Debug.Print Workbooks("Example.xlsm").Name
Debug.Print Workbooks(1).Name
End Sub
When to Use Keys
An example of when to use keys is as follows: Imagine you have a collection of IDs for a 10,000 students along with their marks.
You also have a number of worksheet reports that have lists of student IDs. For each of these worksheets you need to print the mark for each student.
You could do this by adding the 10,000 students to a collection using their student id as they key. When you read an ID from the worksheet you can directly access this student’s marks.
If you didn’t use a key you would have to search through 10,000 IDs for each ID on the report.
Shortcoming of Using Keys in Collections
There are three issues with using keys in collections
You cannot check if the key exists
You cannot change the key
You cannot retrieve the key
VBA contains a class similar to the Collection called the Dictionary. With a Dictionary you always use keys to add an item. The Dictionary provides more functionality to work with keys. If you need more functionality with keys then you may find the Dictionary very useful.
Coming back to Collections: if you will need to directly access a single item then using keys can be very useful. Otherwise you don’t need to use them.
Accessing all items in a Collection
To access all the items in a collection you can use a For loop or a For Each loop. Let’s look at these individually.
Using the For Loop
With a normal For Loop, you use the index to access each item. The following example prints the name of all the open workbooks
Sub AllWorkbook()
Dim i As Long
For i = 1 To Workbooks.Count
Debug.Print Workbooks(i).Name
Next i
End Sub
You can see that we use the range of 1 to Workbooks.Count. The first item is always in postion one and the last item is always in the position specified by the Count property of the collection.
The next example prints out all the items in a user created collection.
Sub UserCollection()
' Declare and Create collection
Dim collFruit As New Collection
' Add items
collFruit.Add "Apple"
collFruit.Add "Pear"
collFruit.Add "Plum"
' Print all items
Dim i As Long
For i = 1 To collFruit.Count
Debug.Print collFruit(i)
Next i
End Sub
Using the For Each
The For Each loop that is a specialised loop the is used for Collections. It doesn’t use the index and the format is shown in the following example
Sub AllWorkbookForEach()
Dim book As Variant
For Each book In Workbooks
Debug.Print book.Name
Next
End Sub
The format of the For loop is:
For i = 1 To Coll.Count
Next
where i is a long and Coll is a collection.
The format of the For Each Loop is:
For Each var In Coll
Next
where var is a variant and Coll is a collection.
To access each the item
For: Coll(i)
For Each: Var
The following example shows the loops side by side for the above user collection example
Sub UseBothLoops()
' Declare and Create collection
Dim collFruit As New Collection
' Add items
collFruit.Add "Apple"
collFruit.Add "Pear"
collFruit.Add "Plum"
' Print all items using For
Dim i As Long
For i = 1 To collFruit.Count
Debug.Print collFruit(i)
Next i
' Print all items using For Each
Dim fruit As Variant
For Each fruit In collFruit
Debug.Print fruit
Next fruit
End Sub
For Each Versus For
It is important to understand the difference between the two loops.
The For Each Loop
is faster
is neater to write
has one order only – low index to high
The For Loop
is slower
is less neater to write
can access in different order
Let’s compare the loops under each of these attributes
Speed
The For Each is considered faster than the For Loop. Nowadays this is only an issue if you have a large collection and/or a slow PC/Network.
Neater
The For Each loop is neater to write especially if you are using nested loops. Compare the following loops. Both print the names of all the worksheets in open workbooks.
Sub PrintNamesFor()
' Print worksheets names from all open workbooks
Dim i As Long, j As Long
For i = 1 To Workbooks.Count
For j = 1 To Workbooks(i).Worksheets.Count
Debug.Print Workbooks(i).Name, Workbooks(i).Worksheets(j).Name
Next j
Next i
End Sub
Sub PrintNamesForEach()
' Print worksheets names from all open workbooks
Dim bk As Workbook, sh As Worksheet
For Each bk In Workbooks
For Each sh In bk.Worksheets
Debug.Print bk.Name, sh.Name
Next sh
Next bk
End Sub
The For Each loop is much neater to write and less likely to have errors.
Order
The order of the For Each loop is always from the lowest index to the highest. If you want to get a different order then you need to use the For Loop. The order of the For Loop can be changed. You can read the items in reverse. You can read a section of the items or you can read every second item.
Sub ReadRightToLeft()
' Go through sheets from right to left
Dim i As Long
For i = ThisWorkbook.Worksheets.Count To 1 Step -1
Debug.Print ThisWorkbook.Worksheets(i).Name
Next i
' Go through first 3 sheets
For i = 1 To 3
Debug.Print ThisWorkbook.Worksheets(i).Name
Next i
' Go through every second sheet
For i = 1 To ThisWorkbook.Worksheets.Count Step 2
Debug.Print ThisWorkbook.Worksheets(i).Name
Next i
End Sub
The For loop gives more flexibility here but the reality is that most of the time the basic order is all you need.
Using Collections with Functions and Subs
Using a Collection as a parameter or return value is very easy to do. We will look at them in turn.
Passing a Collection to a Sub/Function
It is simple to pass a collection to a function or sub. It is passed like any parameter as the following code example shows
Sub UseColl()
' Create collection
Dim coll As New Collection
' Add items
coll.Add "Apple"
coll.Add "Orange"
' Pass to sub
PrintColl coll
End Sub
' Sub takes collection as argument
Sub PrintColl(ByRef coll As Collection)
Dim item As Variant
For Each item In coll
Debug.Print coll
Next
End Sub
You can see how useful the sub PrintColl is in the example. It will print all the elements of ANY collection. The size or type of element does not matter. This shows how flexible collections are to use.
Passing ByVal versus ByRef
One subtle point to keep in mind here is passing by value(By Val) and passing by reference(ByRef) differ slightly.
For a simple variable passing by value means a copy is created. This means if the Function/Sub changes the value will not be changed when you return to the calling procedure.
In the following example we pass total using both ByVal and ByRef. You can see that after we pass using ByRef the value has changed in the calling procedure.
Sub PassType()
Dim total As Long
total = 100
PassByVal total
' Prints 100
Debug.Print total
PassByRef total
' Prints 555
Debug.Print total
End Sub
Sub PassByVal(ByVal total As Long)
' value changed only in this sub
total = 555
End Sub
Sub PassByRef(ByRef total As Long)
' value also changed outside this sub
total = 555
End Sub
Using ByVal and ByRef with a Collection is a bit different. If you add or remove item then the collection in the original caller will also be changed. So the Subs in the following example will both remove the first item of the original collection
Sub RemoveByRef(ByRef coll As Collection)
coll.Remove 1
End Sub
Sub RemoveByVal(ByVal coll As Collection)
coll.Remove 1
End Sub
The reason for this is that a Collection variable contains a pointer. This means it contains the address of the collection rather than the actual collection. So when you add or remove an item you are changing what the pointer is pointing at and not the pointer itself. However if you change the pointer it will be changed outside of the sub.
You don’t need to worry about pointers. All you need to know is how this affects the behaviour of passing a parameter. If you set a collection parameter to nothing then the behaviour depends on if you used ByRef or ByVal.
Using ByRef will reset the original collection
Using ByVal will not change the original collection
' Will empty original collection
Sub PassByRef(ByRef coll As Collection)
Set coll = Nothing
End Sub
' Will NOT empty original collection
Sub PassByVal(ByVal coll As Collection)
Set coll = Nothing
End Sub
Returning a Collection From a Function
Returning a collection from a Function is the same as returning any object. You need to use the Set keyword. In the following example you can see how to return a collection
Sub FruitReport()
Dim coll As Collection
' assign coll to return value
Set coll = CreateCollection
End Sub
Function CreateCollection() As Collection
Dim coll As New Collection
coll.Add "Plum"
coll.Add "Pear"
' Return collection
Set ReadFruit = coll
End Function
Note that you don’t use the New keyword when declaring the collection in the sub FruitReport(). This is because the collection is created in CreateCollection(). When you return the collection you are simple assigning the collection variable to point to this collection.
Conclusion
Collections are a very useful part of VBA. There are much easier to use than Arrays and are very useful when the number of items changes a lot. They have only four properties: Add, Remove, Count and Item. This makes them very easy to master.
I hope you found this post useful. This blog has loads more posts on the important areas of VBA. You can check out all the posts by category here. If you have any queries feel free to email me at paulkellykk@gmail.com.
April 17, 2015
How To Dramatically Reduce VBA Errors
“I am indeed amazed when I consider how weak my mind is and how prone to error.” – Rene Descartes
Introduction
This post shows a simple technique that will vastly reduce the number of errors in your VBA code. I have used this technique thousands of times on countless projects. It will save you considerable time creating applications and it will make your application practically bulletproof.
If you adopt this technique then I guarantee you will see results almost immediately. Reading about it is not enough – you have to actually try it out for yourself. Once you see how useful it is you will want to keep using it.
The simple technique I’m referring to is the Assertion statement. It is simple to use and implement and will provide dramatic results. However don’t be fooled by the simplicity of an Assertion. Used correctly it is an incredibly powerful way of detecting errors in your code.
Before we look at Assertions lets have a quick look at a startling fact about errors

© Wotan777 | Dreamstime.com
A Proud Warrior On The Field At Dawn
A Startling Fact About Errors in Code
According to Steve McConnell in Code Complete: “there are about 15 – 50 errors per 1000 lines of delivered code”.
Just think about this for a moment. If you average the time on each bug to 30 minutes then your are talking 8 to 25 hours spent on errors for every 1000 lines of code.
30 Minutes is an optimistic average. When a bug is found in delivered code many of the following steps are required
Reproduce the bug
Emails about details of the issue
Find the bug
Fix the bug
Update the Bug Report
Create new version of the code
Test the new version
and so on
If you find a bug in development
Find the problem and fix it
This leads us to the following rule
Therefore finding bugs early and close to the cause is a priority. Let’s have a look at your first line of defence when it comes to errors. Then we will look at Assertions
The Front Line in the War on Errors
In VBA there are some basic tools for finding errors. These are very important for catching errors before you run your code. So it’s vital that you use them in your development. I’m going to briefly mention them here.
The Interpreter : The interpreter in VBA checks each line of code as you write it. When you press return it will check for errors in the line and display the error if it finds one. See here for a downloadable list of common errors and how to resolve them.
The Compiler : Before you run your code you should always compile it to find any existing errors. To compile select Debug->Compile VBAProject from the menu.
Note: If you Run your code(Run->Run Macro from menu) it will find some of the same errors. However it will only check in the code that is being run.
Review Source Code from Mz-Tools: MZ-Tools is great free tool that provides extra functionality to the VBA Editor that includes reviewing the source code. This review looks for items such as unused variables, parameters and other useful items.
To use this tool select Other Utilities->Review Source Code from the MZ-Tools toolbar

Using the MZ-Tool to Review Code
Now that we have covered the basic error finding methods lets look at using Assertions.
Why Use Assertions
We have just looked at ways of detecting errors in your code. However certain errors will not appear until you run it. This is where Assertions come into play. A great description of Assertions can be found in the book Debugging Windows Programs (2000 Developmentor Series)
“You can add information to your code to have the program itself automatically detect many types of run-time errors”
The key phrase here is “automatically detect”. Once you add Assertions to your code they will automatically check for errors each time you run your code. This makes it very difficult for many types of errors to exist. So running your code with Assertions is a fantastic way of smoking out errors.
What are Assertions
Assertions are used in development to check your code as it runs. An Assertion is a statement that evaluates to true or false. If it evaluates to false then the code stops at that line. This is useful as it stops you close to the cause of the error.
Let’s explain using an analogy. Imagine the different paths through your code were the streets of a city and variables were vans that drove the streets. Assertions would then be checkpoints that ensure the vans(variables) contain valid goods(values) before they are allowed to pass.

© Marcogarrincha | Dreamstime.com
If the city was full of checkpoints it would be very difficult for the Van to travel far with invalid goods. It’s the same with code. The more Assertions there are the harder for the code to run for long with errors.
In the city solution the checkpoints would affect performance. They would slow the city traffic considerably. With Assertions there are no performance issues. They are turned off when you deliver your software to the user. This means you can add as many Assertions as you like and it will have no affect on how your code runs.
How to Create A VBA Assertion
It is simple to create an assertion in VBA. You use the function Debug.Assert followed by a Condition.
Debug.Assert Worksheets.Count > 0
Debug.Assert Text <> ""
Here are some more examples
' This will fail if readRow is not 1 or greater
Dim readRow As Long
Debug.Assert readRow > 0
' This will fail if month is not between 1 and 12
Dim month As Long
Debug.Assert month >= 1 And month
When the code meets a Debug.Assert line it evaluates the condition. If the condition evaluates to false then the code stops on this line. If it evaluates to true then the code simply continues on.
When to Use Assertions
The best way to use Assertions is to test the following items:
The input values of a Sub/Function
A value before it is returned from a function
A value that is received from a function
A global variable before it is used
The following functions uses Assertions to test
the values of the input parameters (Precondition)
the value that is being returned(Postcondition)
Function GetType(price As Long, shipType As String) As Double
' TEST THE INPUTS(Preconditions)
Debug.Assert price > 0 And price < 100 Debug.Assert Len(shipType) = 1 ' Do some calcus Dim newVal As Double If shipType = "A" Then newVal = price 3.99 ElseIf shipType = "B" Then newVal = price 5.99 Else newVal = price 0 End If ' TEST THE RETURN VALUE(Postconditions) Debug.Assert newVal > 0
' Return the value
GetType = newVal
End Function
In the next example we use an Assertion to test the return value from a function
Sub RunReport()
Dim total as long
total = CalculateTotal()
' check that total is in the expected range(1 to 999)
Debug.Assert total>0 and total
Assertions Versus Error Handling
Error handling is used in code to anticipate error conditions and deal with them. For example sometimes a workbook you are trying to open my have been moved, deleted or renamed. In this case the code should report the error and return to the state before it tried to use this file.
Let’s look at a second example. Imagine you use a software application to play music files. If you try to play an invalid file the application should inform you the file is incompatible. The application should then return to it’s previous state – ready for you to select a file to play as if nothing happened. The application not stop working or begin working incorrectly.
The following code shows a simple example of error handling. We use the Dir function to check the file exists. If not then we inform the user there is a problem. We only attempt to open the file when we know it actually exists.
Sub ReadData(ByVal filename As String)
' Use Dir to check the file exists
If Dir(filename) = "" Then
' Tell the user the file does not exist
MsgBox "Could not find the file " filename
Else
' Open workbook
Workbooks.Open filename
End If
End Sub
The difference between Assertions and Error Handling is that
Assertions deal with values coming from an internal source
Assertions are used to inform the programmer of errors and not the user
Error Handling deals with errors coming from an external source e.g. opening files, user input, spreadsheet data etc.
Let’s update the example above so it uses both Assertions and Error Handling.
Sub ReadData(ByVal filename As String)
' USE ASSERTION TO CHECK VALUES FROM INSIDE APPLICATION
Debug.Assert filename <> ""
' USE ERROR HANDLING TO DEAL WITH ERRORS FROM OUTSIDE APPLICATION
' Use Dir to check the file exists
If Dir(filename) = "" Then
' Inform the user
MsgBox "Could not find the workbook: " filename
Else
' Open workbook
Workbooks.Open filename
End If
End Sub
If these seems confusing just remember you mostly use assertions on arguments and return values.
How to Turn Assertions On or Off
Assertions are used to check your code during development or maintenance. When you give your application to a user then you turn the Assertions off. This provides us with two really great advantages:
You can add as many Assertions as you like as it will not have any impact on the code you give the user
If in doubt about adding an Assertion then add it anyway. You can easily remove it and it won’t affect the user.
Let’s look at how to turn Assertions On and Off.
To turn Assertions On/Off we use a special type of If statement to surround our code. This is the #If statement – note the #character before the If . First of all we need to create a “Conditional Argument” that we can use in this if statement
Select Tool->VBAProject Properties from the VBA menu.
You can see in the screen shot that we have written Debugging = 1 in the cryptically named textbox “Conditional Compilation Arguments”. Debugging can be any name we like and =1 means it is currently true.
We use this argument to decide if we are going to use certain code when our application runs. The following code shows how to use the #If statement with the compilation argument i.e. in this case Debugging
Function GetType(price As Long, shipType As String) As Double
#If Debugging Then
' Test inputs(Preconditions)
Debug.Assert price > 0 And price < 100
Debug.Assert Len(shipType) = 1
#End If
End Function
In the above example the assertions are only used when Debugging is turned on(set to a value other than 0). When we turn debugging off this code will not be used. When we want to turn off the Assertions we simply change the Conditional Argument in the dialog to Debugging = 0. This means all the code inside the #If Debugging statements will not be used.
What to Avoid
Never put executable code inside a #If statement. Only use code that will help you when debugging. In VBA this is essentially the two statement types Debug.Assert and Debug.Print. The second statement writes to the Immediate Window(Ctrl G or View->Immediate Window from Menu) and it useful for testing code.
The following example is something you should avoid doing
#If Debugging Then
' Don't use executable inside #If statements
Debug.Assert WriteData() = True
#End If
End Sub
Function WriteData() As Boolean
WriteData = False
End Function
The correct way to write this code is shown in the following example
Sub TestAssert()
Dim success As Boolean
success = WriteData()
#If Debugging Then
Debug.Assert success = True
#End If
End Sub
Function WriteData() As Boolean
WriteData = False
End Function
In the second example there is no executable code in the #If statement. This is important as it means the code will run exactly the same when you turn debugging on or off.
Using Assertions With Collections and Objects
When you are using a Collection you should check two things:
If the Collection has been created
If the collection has elements
Lets look at how to create a collection. We can declare in one line and create in a second line like this code shows
Sub CreateCollection1()
' Declare a collection variable
Dim coll As Collection
' Assign coll to a new empty collection
Set coll = New Collection
End Sub
we can also declare and create in one single line as the next example shows.
Sub CreateCollection2()
' Declare and create collection in one line
Dim coll As New Collection
End Sub
In the first example the variable Coll is set to Nothing until we use the Set command to create a new Collection for it.
So when using Collections(or any object) we need first to check they are not empty(Set to Nothing). The following example shows how to check an object is set to something
Sub TestCollection(coll As Collection)
Debug.Assert Not coll Is Nothing
End Sub
This code may seem strange as it has two negatives – Not and Nothing. However all objects are tested this way so you can use it even if you don’t understand it at first.
The next example shows Assertions that test a Workbook and Worksheet object to ensure they have been assigned to something.
Sub WriteData(wk As Workbook, sh As Worksheet)
Debug.Assert Not wk Is Nothing
Debug.Assert Not sh Is Nothing
End Sub
When using Collections it is also a good idea to check that it contains some elements
Sub TestCollection(coll As Collection)
Debug.Assert Not coll Is Nothing
Debug.Assert coll.Count >= 1
End Sub
Summary
The following is a summary of the main points of this post
Finding errors early is vital
It will save time and improve quality
Assertions find errors during run time
Assertions are created in VBA using Debug.Assert
They are used during development and mantainence
Assertions are not a substitute for error handling code
Assertions provide information to the programmer not the user
If in doubt add the Assertion anyway. You can easily remove it from the code.
Assertions are turned off when the code is released. It is simple to do this in VBA.
Major Advantages of Assertions
It is simple to add them to your code
They automatically detect errors when your code is running
They have no performance issues as you turn them off upon release.
I hope you found this post beneficial and that it conveyed how useful Assertions are. They really are a fantastic tool and will greatly improve your programming experience.
Please feel free to subscribe to my newsletter and get exclusive VBA content that you cannot find here on the blog, as well as free access to my eBook, How to Ace the 21 Most Common Questions in VBA which is full of examples you can use in your own code.
The post How To Dramatically Reduce VBA Errors appeared first on Excel Macro Mastery.
How To Reduce VBA Errors by up to 70% Using This Proven Technique
“I am indeed amazed when I consider how weak my mind is and how prone to error.” – Rene Descartes

© Wotan777 | Dreamstime.com
A Proud Warrior On The Field At Dawn
Introduction
This post shows a simple technique that will vastly reduce the number of errors in your VBA code. I have used this technique thousands of times on countless projects. It will save you considerable time creating applications and it will make your application practically bulletproof.
If you adopt this technique then I guarantee you will see results almost immediately. Reading about it is not enough – you have to actually try it out for yourself. Once you see how useful it is you will want to keep using it.
The simple technique I’m referring to is the Assertion statement. It is simple to use and implement and will provide dramatic results. However don’t be fooled by the simplicity of an Assertion. Used correctly it is an incredibly powerful way of detecting errors in your code.
Before we look at Assertions lets have a quick look at a startling fact about errors
A Startling Fact About Errors in Code
According to Steve McConnell in Code Complete: “there are about 15 – 50 errors per 1000 lines of delivered code”.
Just think about this for a moment. If you average the time on each bug to 30 minutes then your are talking 8 to 25 hours spent on errors for every 1000 lines of code.
30 Minutes is an optimistic average. When a bug is found in delivered code many of the following steps are required
Reproduce the bug
Emails about details of the issue
Find the bug
Fix the bug
Update the Bug Report
Create new version of the code
Test the new version
and so on
If you find a bug in development
Find the problem and fix it
This leads us to the following rule
Therefore finding bugs early and close to the cause is a priority. Let’s have a look at your first line of defence when it comes to errors. Then we will look at Assertions
The Front Line in the War on Errors
In VBA there are some basic tools for finding errors. These are very important for catching errors before you run your code. So it’s vital that you use them in your development. I’m going to briefly mention them here.
The Interpreter : The interpreter in VBA checks each line of code as you write it. When you press return it will check for errors in the line and display the error if it finds one. See here for a downloadable list of common errors and how to resolve them.
The Compiler : Before you run your code you should always compile it to find any existing errors. To compile select Debug->Compile VBAProject from the menu.
Note: If you Run your code(Run->Run Macro from menu) it will find some of the same errors. However it will only check in the code that is being run.
Review Source Code from Mz-Tools: MZ-Tools is great free tool that provides extra functionality to the VBA Editor that includes reviewing the source code. This review looks for items such as unused variables, parameters and other useful items.
To use this tool select Other Utilities->Review Source Code from the MZ-Tools toolbar

Using the MZ-Tool to Review Code
Now that we have covered the basic error finding methods lets look at using Assertions.
Why Use Assertions
We have just looked at ways of detecting errors in your code. However certain errors will not appear until you run it. This is where Assertions come into play. A great description of Assertions can be found in the book Debugging Windows Programs (2000 Developmentor Series)
“You can add information to your code to have the program itself automatically detect many types of run-time errors”
The key phrase here is “automatically detect”. Once you add Assertions to your code they will automatically check for errors each time you run your code. This makes it very difficult for many types of errors to exist. So running your code with Assertions is a fantastic way of smoking out errors.
What are Assertions
Assertions are used in development to check your code as it runs. An Assertion is a statement that evaluates to true or false. If it evaluates to false then the code stops at that line. This is useful as it stops you close to the cause of the error.
Let’s explain using an analogy. Imagine the different paths through your code were the streets of a city and variables were vans that drove the streets. Assertions would then be checkpoints that ensure the vans(variables) contain valid goods(values) before they are allowed to pass.

© Marcogarrincha | Dreamstime.com
If the city was full of checkpoints it would be very difficult for the Van to travel far with invalid goods. It’s the same with code. The more Assertions there are the harder for the code to run for long with errors.
In the city solution the checkpoints would affect performance. They would slow the city traffic considerably. With Assertions there are no performance issues. They are turned off when you deliver your software to the user. This means you can add as many Assertions as you like and it will have no affect on how your code runs.
How to Create A VBA Assertion
It is simple to create an assertion in VBA. You use the function Debug.Assert followed by a Condition.
Debug.Assert Worksheets.Count > 0
Debug.Assert Text <> ""
Here are some more examples
' This will fail if readRow is not 1 or greater
Dim readRow As Long
Debug.Assert readRow > 0
' This will fail if month is not between 1 and 12
Dim month As Long
Debug.Assert month >= 1 And month
When the code meets a Debug.Assert line it evaluates the condition. If the condition evaluates to false then the code stops on this line. If it evaluates to true then the code simply continues on.
When to Use Assertions
The best way to use Assertions is to test the following items:
The input values of a Sub/Function
A value before it is returned from a function
A value that is received from a function
A global variable before it is used
The following functions uses Assertions to test
the values of the input parameters (Precondition)
the value that is being returned(Postcondition)
Function GetType(price As Long, shipType As String) As Double
' TEST THE INPUTS(Preconditions)
Debug.Assert price > 0 And price < 100
Debug.Assert Len(shipType) = 1
' Do some calcus
Dim newVal As Double
If shipType = "A" Then
newVal = price + 3.99
ElseIf shipType = "B" Then
newVal = price + 5.99
Else
newVal = price + 0
End If
' TEST THE RETURN VALUE(Postconditions)
Debug.Assert newVal > 0
' Return the value
GetType = newVal
End Function
In the next example we use an Assertion to test the return value from a function
Sub RunReport()
Dim total as long
total = CalculateTotal()
' check that total is in the expected range(1 to 999)
Debug.Assert total>0 and total
Assertions Versus Error Handling
Error handling is used in code to anticipate error conditions and deal with them. For example sometimes a workbook you are trying to open my have been moved, deleted or renamed. In this case the code should report the error and return to the state before it tried to use this file.
Let’s look at a second example. Imagine you use a software application to play music files. If you try to play an invalid file the application should inform you the file is incompatible. The application should then return to it’s previous state – ready for you to select a file to play as if nothing happened. The application not stop working or begin working incorrectly.
The following code shows a simple example of error handling. We use the Dir function to check the file exists. If not then we inform the user there is a problem. We only attempt to open the file when we know it actually exists.
Sub ReadData(ByVal filename As String)
' Use Dir to check the file exists
If Dir(filename) = "" Then
' Tell the user the file does not exist
MsgBox "Could not find the file " + filename
Else
' Open workbook
Workbooks.Open filename
End If
End Sub
The difference between Assertions and Error Handling is that
Assertions deal with values coming from an internal source
Assertions are used to inform the programmer of errors and not the user
Error Handling deals with errors coming from an external source e.g. opening files, user input, spreadsheet data etc.
Let’s update the example above so it uses both Assertions and Error Handling.
Sub ReadData(ByVal filename As String)
' USE ASSERTION TO CHECK VALUES FROM INSIDE APPLICATION
Debug.Assert filename <> ""
' USE ERROR HANDLING TO DEAL WITH ERRORS FROM OUTSIDE APPLICATION
' Use Dir to check the file exists
If Dir(filename) = "" Then
' Inform the user
MsgBox "Could not find the workbook: " + filename
Else
' Open workbook
Workbooks.Open filename
End If
End Sub
If these seems confusing just remember you mostly use assertions on arguments and return values.
How to Turn Assertions On or Off
Assertions are used to check your code during development or maintenance. When you give your application to a user then you turn the Assertions off. This provides us with two really great advantages:
You can add as many Assertions as you like as it will not have any impact on the code you give the user
If in doubt about adding an Assertion then add it anyway. You can easily remove it and it won’t affect the user.
Let’s look at how to turn Assertions On and Off.
To turn Assertions On/Off we use a special type of If statement to surround our code. This is the #If statement – note the #character before the If . First of all we need to create a “Conditional Argument” that we can use in this if statement
Select Tool->VBAProject Properties from the VBA menu.
You can see in the screen shot that we have written Debugging = 1 in the cryptically named textbox “Conditional Compilation Arguments”. Debugging can be any name we like and =1 means it is currently true.
We use this argument to decide if we are going to use certain code when our application runs. The following code shows how to use the #If statement with the compilation argument i.e. in this case Debugging
Function GetType(price As Long, shipType As String) As Double
#If Debugging Then
' Test inputs(Preconditions)
Debug.Assert price > 0 And price < 100
Debug.Assert Len(shipType) = 1
#End If
End Function
In the above example the assertions are only used when Debugging is turned on(set to a value other than 0). When we turn debugging off this code will not be used. When we want to turn off the Assertions we simply change the Conditional Argument in the dialog to Debugging = 0. This means all the code inside the #If Debugging statements will not be used.
What to Avoid
Never put executable code inside a #If statement. Only use code that will help you when debugging. In VBA this is essentially the two statement types Debug.Assert and Debug.Print. The second statement writes to the Immediate Window(Ctrl G or View->Immediate Window from Menu) and it useful for testing code.
The following example is something you should avoid doing
#If Debugging Then
' Don't use executable inside #If statements
Debug.Assert WriteData() = True
#End If
End Sub
Function WriteData() As Boolean
WriteData = False
End Function
The correct way to write this code is shown in the following example
Sub TestAssert()
Dim success As Boolean
success = WriteData()
#If Debugging Then
Debug.Assert success = True
#End If
End Sub
Function WriteData() As Boolean
WriteData = False
End Function
In the second example there is no executable code in the #If statement. This is important as it means the code will run exactly the same when you turn debugging on or off.
Using Assertions With Collections and Objects
When you are using a Collection you should check two things:
If the Collection has been created
If the collection has elements
Lets look at how to create a collection. We can declare in one line and create in a second line like this code shows
Sub CreateCollection1()
' Declare a collection variable
Dim coll As Collection
' Assign coll to a new empty collection
Set coll = New Collection
End Sub
we can also declare and create in one single line as the next example shows.
Sub CreateCollection2()
' Declare and create collection in one line
Dim coll As New Collection
End Sub
In the first example the variable Coll is set to Nothing until we use the Set command to create a new Collection for it.
So when using Collections(or any object) we need first to check they are not empty(Set to Nothing). The following example shows how to check an object is set to something
Sub TestCollection(coll As Collection)
Debug.Assert Not coll Is Nothing
End Sub
This code may seem strange as it has two negatives – Not and Nothing. However all objects are tested this way so you can use it even if you don’t understand it at first.
The next example shows Assertions that test a Workbook and Worksheet object to ensure they have been assigned to something.
Sub WriteData(wk As Workbook, sh As Worksheet)
Debug.Assert Not wk Is Nothing
Debug.Assert Not sh Is Nothing
End Sub
When using Collections it is also a good idea to check that it contains some elements
Sub TestCollection(coll As Collection)
Debug.Assert Not coll Is Nothing
Debug.Assert coll.Count >= 1
End Sub
Summary
The following is a summary of the main points of this post
Finding errors early is vital
It will save time and improve quality
Assertions find errors during run time
Assertions are created in VBA using Debug.Assert
They are used during development and mantainence
Assertions are not a substitute for error handling code
Assertions provide information to the programmer not the user
If in doubt add the Assertion anyway. You can easily remove it from the code.
Assertions are turned off when the code is released. It is simple to do this in VBA.
Major Advantages of Assertions
It is simple to add them to your code
They automatically detect errors when your code is running
They have no performance issues as you turn them off upon release.
I hope you found this post beneficial and that it conveyed how useful Assertions are. They really are a fantastic tool and will greatly improve your programming experience.
This blog provides many other in-depth posts on the important areas of VBA. These will help you get the best from this fantastic Excel programming language. You can check out all the posts here.
April 13, 2015
The Complete Guide to Functions and Subs in Excel VBA
“I’m happy to share what I can, because I’m in it for the love of programming.” – John Carmack, creator of Doom, Quake and Oculus VR.

© Ariwasabi | Dreamstime.com
Introduction
What are Functions and Subs?
Functions and Sub are are very similar in VBA. They are both procedures where you write your code. However there are differences and these are important to understand. In this post I am going to look at Fuctions and Sub in detail and answer the vital questions including
What is the difference between them
When to use a Sub and when to use a Function?
How do you run them?
Can I return values
How do I pass parameters to them
What are optional parameters
and much more
If are looking for a quick guide to using Functions and Subs then go to the first section. However make sure to come back to the post as it has important information about using Functions and Subs that you don’t want to miss out on.
Functions and Subs: A Quick Guide
The following table provides a simple overview of using Functions and Subs.

A Quick Guide to Subs and Functions
Note: A Function can also be called like a Sub when you are not returning a value.
What is a Sub?
In Excel VBA a Sub and a Macro are exactly the same thing! This often leads to confusion so it is a good idea to remember it. For the rest of this post I will refer to them as Subs.
A Sub/Macro is where you write your VBA code. When you run a Sub all the lines of code it contains are executed.
The following is an example of an empty sub
Sub WriteValues()
End Sub
You declare the Sub by using Sub and the name. When you give it a name keep the following in mind
The name must begin with a letter and cannot contain spaces.
The name must be unique in the current workbook
The end of the Sub is marked by the line End Sub.
When you create your Sub you can add some code like the following example shows
Sub WriteValues()
Range("A1") = 6
End Sub
What is a Function?
A Function is very similar to a Sub. The major difference is that a Function can return a value – a Sub cannot. There are other differences which we will look at but this is the main one.
You normally create a function when you want to return a value.
Creating a Function is similar to creating a Sub
Function PerformCalc()
Function Sub
It is optional to add a return type to a function. However it is considered good practice to do so. If you accidentally return the wrong type then it will be flagged as an error by VBA which is good.
The next example shows you how to specify the return type
Function PerformCalc() As Long
Function Sub
You can see this is simple to how you declare a variable. You can return any type you can declare as a variable including objects and collections.
A Quick Comparison
Sub: Cannot return a value
Function: Returns a value
Sub: You can run it from VBA\Button\Event etc.
Function: You cannot run it from VBA\Button\Event etc. You can run in two ways:
Call it from another Sub/Function
When you create a Function it appears in the worksheet function list for the current workbook
Function: How to Return Values
To return a value from a function you assign the value to the name of the Function. The following examples demonstrates this
Function GetAmount() As Long
' Returns 55
GetAmount = 55
End Function
Function GetName() As String
' Returns John
GetName = "John"
End Function
When you return a value from a function you will obviously need to get it back to the calling Function/Sub. You do this by assigning the Function call to a variable. The following example shows this
Sub WriteValues()
Dim Amount As Long
' Get value from GetAmount function
Amount = GetAmount
End Sub
Function GetAmount() As Long
GetAmount = 55
End Function
You can easily test your return value using Debug.Print. This will write values to the Immediate Window. To view select View->Immediate Window(shortcut Ctrl + G).
Sub WriteValues()
' Print return value to Immediate Window
Debug.Print GetAmount
End Sub
Function GetAmount() As Long
GetAmount = 55
End Function
Note: When you assign the return value of a function you need to use parenthesis around the function arguments
Passing Arguments
Arguments are passed to Subs and Functions in the same way. One important thing to keep in mind is that if you use parenthesis when calling the Function/Sub then passing by reference(ByRef) does not work. We’ll have a look at this later in the section.
The following shows how to declare a parameter for a Sub and Function
Function CalcValue(x As Long)
End Function
Sub WriteValue(x As Long)
End Sub
You can see it is similar to creating a variable except that we don’t use Dim. You can specify two ways of passing a variable: ByRef or ByVal.
' Pass by value
Sub WriteValue1(ByVal x As Long)
End Function
' Pass by reference
Sub WriteValue2(ByRef x As Long)
End Sub
' No type used so it is ByRef
Sub WriteValue3(x As Long)
End Sub
If you don’t specify the type then ByRef is the type as you can see in the third sub of the example.
The different between these type is:
ByVal - Creates a copy of the variable you pass.
This means if you change the value of the parameter it will not be changed when you return to the calling Sub/Function
ByRef - Creates a reference of the variable you pass.
This means if you change the value of the parameter variable it will be changed when you return to the calling Sub/Function.
The following code example shows this
Sub Test()
Dim x As Long
' Pass by value - x will not change
x = 1
Debug.Print "x before ByVal is"; x
SubByVal x
Debug.Print "x after ByVal is"; x
' Pass by reference - x will change
x = 1
Debug.Print "x before ByRef is"; x
SubByRef x
Debug.Print "x after ByRef is"; x
End Sub
Sub SubByVal(ByVal x As Long)
' x WILL NOT change outside as passed ByVal
x = 99
End Sub
Sub SubByRef(ByRef x As Long)
' x WILL change outside as passed ByRef
x = 99
End Sub
The result of this is:
x before ByVal is 1
x after ByVal is 1
x before ByRef is 1
x after ByRef is 99
You should avoid passing basic variable types using ByRef. There are two main reasons for this
The person passing a value may not expect it to change and this can lead to bugs that are difficult to detect
Using parenthesis when calling prevents ByRef working – see next sub section
Therefore you should always declare your parameters as ByVal for basic types.
A Little-Known Pitfall of ByRef
There is one thing you must be careful of when using ByRef parameters. If you use parenthesis then the Sub/Function cannot change the variable you pass even if it is passed ByRef . In the following example we call the Sub first without parenthesis and then with parenthesis. This causes the code to behave differently.
Sub Test()
Dim x As Long
' Call using without Parenthesis - x will change
x = 1
Debug.Print "x before (no parenthesis): "; x
SubByRef x
Debug.Print "x after (no parenthesis): "; x
' Call using with Parenthesis - x will not change
x = 1
Debug.Print "x before (with parenthesis): "; x
SubByRef (x)
Debug.Print "x after (with parenthesis): "; x
End Sub
Sub SubByRef(ByRef x As Long)
x = 99
End Sub
As you
So as I said in the last section you should avoid passing a variable using ByRef and instead use ByVal.
This means
The variable you pass will not be accidentally changed
Using parenthesis will not affect the behaviour
Custom Function vs Worksheet Function
When you create a function it appears in the function list for that workbook. Look at the function in the next example.
Sub MyNewFunction()
MyNewFunction = 99
End Sub
If you add this to a workbook then the function will appear in the function list. Type “=My” into the function box and the function will appear as shown in the following screensheet.
If you use this function in a cell you will get the result 99 in the cell as that is what the function returns.
Conclusion
The main points of this post are
Subs and Macros are the same thing in VBA
Use a Sub to write most of your code
Use a Function if you need to return a value
A Sub can be run in many ways
Functions must be called by a Sub/Function or used as a worksheet function
Functions appear in the workbook function list for the current workbook
ByRef allows the Function\Sub to change the original argument
If you call a Function\Sub with parenthesis then ByRef will not work
This post provided and in-depth look and functions and subs. I hope you found it beneficial. You may want to check out some of my other in-depth posts on the important elements of VBA – A Quick Guide to All the Posts
April 7, 2015
How To Start From Scratch With VBA in Excel
“The secret of getting ahead is getting started” – Mark Twain.
Have you just started with VBA in Excel?
Would you like to learn VBA but feel it is too complex?
Are you a frequent Excel user who would love to know more about macros?
If you answered yes to any of these questions then this post it for you. When you finish reading it you will be able to create and run simple macros using VBA.
This posts uses Excel 2013 but is also valid for Excel 2007/2010.
What is VBA in Excel
VBA is the programming language, Visual Basic for Applications. This language comes pre-installed with Excel. It is very powerful and allows you to extend the functionality of Excel.
You will not only find VBA in Excel, but also in any Microsoft Office application such as Microsoft Word, Access and Outlook.
Step 1 Make the Developer Tab Visible
The Developer Tab is normally visible by default on your ribbon. If not you can make it visible using the following steps
1. Right click on the ribbon. In the list that appears select “Customize the Ribbon”
2. In the dialog that appears you will see a list of tabs on the right hand side. Ensure that “Developer” is checked on.
Step 2 Check Your Security Setting
The next step is to ensure your Macro settings are correct. On the Developer Ribbon, Click on the “Macro Security” button under the “Code” section.
You security settings should match the settings in the screenshot below
Step 3 Save as a Correct File Type
If you workbook has Macros then you must save it as a Macro Enabled Workbook. It is a good idea to do this in the beginning so as to avoid the potential lost of code.
Select File->Save As and choose “Macro Enabled Workbook” from the File type. Then click on Save.
Step 4 Enter the Visual Basic Editor
To enter the Visual Basic editor click on the Visual Basic icon on the Developer tab of the Ribbon. Alternatively you can press Alt F11 on the keyboard
Step 5 Create a Module
Macros are stored in Modules so create a module.
Look in the VBA Project Window. If the window is not visible the select “View” ->”Project Explorer” from the menu (shortcut Ctrl key and R).
Select the workbook where you want to place the code. The workbooks will be in parenthesis beside “VBAProject”. Each open workbook will have an entry like this in the VBA Project window
Right click on the workbook where you wish to place the code. Select “Insert” and then “Module”.
a new module will appear:
When you double click on a Module in the VBA Project window the code of that module is displayed in the main code window. When a new module is created it normally doesn’t contain any code(note it may contain “Option Explicit” if you have this option turned on).
Step 6 Create a Macro
Type “Sub MyFirstMacro” in the main code window and press return. You should have the following
Step 7 Add Some Code to Your Macro
Use MsgBox “Hello World”. This will display a dialog with “Hello World” to the user
Step 8 Run Your Macro
To run your macro:
Click anywhere inside the Macro
Select Run->Run Sub/UserForm
Note: If the cursor is not inside a Macro then VBA will display a list of available Macros and ask you to select one to run.
You should get a dialog like this
Conclusion
This post showed you how to get up and running using VBA. It went through the steps for setting up correctly and ended with you running a macro.
You might like to try our other popular posts such as The Complete Guide To Workbooks in Excel VBA or click here to view all the posts on this site by category.
Please feel free to subscribe to my newsletter and get exclusive VBA content that you cannot find here on the blog, as well as free access to my eBook, How to Ace the 21 Most Common Questions in VBA which is full of examples you can use in your own code.
The post How To Start From Scratch With VBA in Excel appeared first on Excel Macro Mastery.
How To Start From Scratch With Excel VBA
“The secret of getting ahead is getting started” – Mark Twain.
Would you like to learn VBA but feel it is too complex?
Are you a frequent Excel user who would love to know more about macros?
Have you just started with Excel VBA?
If you answered yet to any of these questions then this post it for you. When you have finished you will be able create and run simple macro using VBA.
This posts uses Excel 2013 but is also valid for Excel 2007/2010.
Step 1 Ensure the Developer Tab is Visible
The Developer Tab is normally visible by default on your ribbon. If not you can make it visible using the following steps
1. Right click on the ribbon. In the list that appears select “Customize the Ribbon”
2. In the dialog that appears you will see a list of tabs on the right hand side. Ensure that “Developer” is checked on.
Step 2 Ensure Your Security Setting are Correct
The next step is to ensure your Macro settings are correct. On the Developer Ribbon, Click on the “Macro Security” button under the “Code” section.
You security settings should match the settings in the screenshot below
Step 3 Save as a Macro Enabled Workbook
If you workbook has Macros then you must save it as a Macro Enabled Workbook. It is a good idea to do this in the beginning so as to avoid the potential lost of code.
Select File->Save As and choose “Macro Enabled Workbook” from the File type. The click on Save.
Step 4 Enter the Visual Basic Environment
To enter the Visual Basic editor click on the Visual Basic icon on the Developer tab of the Ribbon. Alternatively you can press Alt + F11 on the keyboard
Step 5 Create a Module
Macros are stored in Modules so create a module.
Look in the VBA Project Window. If the window is not visible the select “View” ->”Project Explorer” from the menu (shortcut Ctrl + R).
Select the workbook where you want to place the code. The workbooks will be in parenthesis beside “VBAProject”. Each open workbook will have an entry like this in the VBA Project window
Right click on the workbook where you wish to place the code. Select “Insert” and then “Module”.
a new module will appear:
When you double click on a Module in the VBA Project window the code of that module is displayed in the main code window. When a new module is created it normally doesn’t contain any code(note it may contain “Option Explicit” if you have this option turned on).
Step 6 Create a Macro
Type “Sub MyFirstMacro” in the main code window and press return. You should have the following
Step 7 Add Some Code to Your Macro
Use MsgBox “Hello World”. This will display a dialog with “Hello World” to the user
Step 8 Run Your Macro
To run your macro:
Click anywhere inside the Macro
Select Run->Run Sub/UserForm
Note: If the cursor is not inside a Macro then VBA will display a list of available Macros and ask you to select one to run.
You should get a dialog like this
Conclusion
This post showed you how to get up and running using VBA. It went through the steps for setting up correctly and ended with you running a macro. If you found this post useful the you might like to try our other posts such as The Complete Guide To Workbooks in Excel VBA or The Complete Guide to Ranges and Cells in Excel VBA.
March 5, 2015
The Ultimate Guide to Loops in Excel VBA
“Nearly all men can stand adversity, but if you want to test a man’s character, give him power” – Abraham Lincoln.

© Heysues23 | Dreamstime.com – Fair Rides Photo
Introduction
Loops are by far the most powerful component of VBA. They are the rocket fuel of your Macros. They can perform tasks in milliseconds that would take humans hours. They dramatically reduce the lines of code you need.
If you have never used loops before then this post is a great place to start. The aim here is to provide you with an in-depth guide to using loops, written in plain English.
The following questions will be addressed
What are Loops?
Why you need them?
When should you use them?
How do they work?
Which one should you in a given situation?
The first section of the post provides a quick guide to loops. If you are here looking for some quick info on loops then this is for you.
Otherwise you can skip to the second section where we start with a very important question – what are loops and why do we need them?
Quick Guide To Loops
There are 4 types of loops in VBA. The Do Loop can be used in 4 ways. The following table provides a quick guide to loops

A quick guide to loops in Excel VBA
What are Loops and Why Do You Need Them?
A loop is simply a way of running the same lines of code a number of times. Obviously running the same code over and over would give the same result. What is important to understand is that the lines of code normally contain a variable that changes slightly each time.
For example a loop could write to A1, then A2, A3 and so on. The slight change each time is the row.
Let’s look at a simple example.
Example 1: Printing 1 to 5
The following code prints the values 1 to 5 in the Immediate Window.
Debug.Print 1
Debug.Print 2
Debug.Print 3
Debug.Print 4
Debug.Print 5
The Immediate Window
If you have not used the Immediate Window before then this section will get you up to speed quickly.
Note: The function Debug.Print writes values to the Immediate Window. To view this window select View->Immediate Window from the menu( Shortcut is Ctrl + G)
Example 2: Printing 1 to 20
Now imagine we want to print out the numbers 1 to 20. We would need to add 15 more lines using the same code. However using a loop we only need to write Debug.Print once.
For i = 1 To 20
Debug.Print i
Next i
The output is

Output
If we needed print the numbers 1 to 1000 then we only need to change the 20 to 1000. Normally in code you would use a variable instead of the values 20 or 1000. This gives you greater flexibility. It allows you to decide the number of times you wish to run the loop when the Macro runs. The following example explains this.
Example 3: Counting Fruit Sold
A common task in Excel is read to the last row of a sheet with data. So the way you would do this is by first finding the last row with data and then using the number of this row in the loop. Then if more lines of data are added the code will still work fine.
Let’s have a look how you would do this with code. Imagine you receive a sheet with a list of fruit types that have been sold each day. You want to count the number of Oranges sold and this list will vary in size depending on sales. The following screenshot shows an example of this list

Sample Data of Fruit Sales
We can use the code to count the oranges
Sub CountFruit()
' Get the last row with text
Dim LastRow As Long
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
Dim i As Long, Total As Long
' Use LastRow in loop
For i = 2 To LastRow
' Check if cell has text "Orange"
If Cells(i, 1).Value = "Oranges" Then
' Add value in column B to total
Total = Total + Cells(i, 2).Value
End If
Next i
' Print total
Debug.Print "Total oranges sold was:"; Total
End Sub
You can try this code for yourself. Change the number of fruit items and you will see that the code still works fine.
If you were to increase the number fruit items to a large value like 10,000 then you hardly notice the difference in the time it takes to run – almost instantly. Loops are super fast. This is what makes them so powerful. Imagine performing a manual task on 10,000 cells. It would take a considerable amount of time.
You may be thinking that excel functions like Sum and Count are powerful as they can also perform a task with a large number of cells quickly. This is true but if you looked at the original code of the function you would find it contains a loop.
Advantages
To conclude this section we will list the major advantages of using loops
They reduce the lines code you need
They are flexible
They are fast
In the next sections we will look at the different types of loops and how to use them.
The For Loop
In VBA the For loop is the most common loop you will use. The For Loop is used when you can determine the number of times it will be run. For example if you want to repeat something twenty times.
Format of the Loop
A for loop is constructed as follows
For = to
Next
The start and end values can be variables. Also the variable after Next is optional but it is useful and it makes it clear which for loop it belongs to.
How a Loop Works
Let’s look at a simple for loop that prints the numbers 1 to 3
Dim i As Long
For i = 1 To 3
Debug.Print i
Next i
How this code works is as follows
i is set to 1
The value of i(now 1) is printed
i is set to 2
The value of i(now 2) is printed
i is set to 3
The value of i(now 3) is printed
If we did not use a loop then the equivalent code would be
Dim i As Long
i = i + 1
Debug.Print i
i = i + 1
Debug.Print i
i = i + 1
Debug.Print i
The “i = i + 1″ line is used to add 1 to i and is a common way in programming to update a counter.
Using Step
You can see that i is increased by one each time. This is the default. You can specify this interval using Step. The next example shows you how to do this
' Prints the even numbers i.e. 2,4,6,8 ... 20
For i = 2 To 20 Step 2
Debug.Print i
Next i
You can use a negative number with Step which will count in reverse
' Prints the even numbers in reverse i.e. 20,18,16,14 ... 2
For i = 20 To 2 Step -2
Debug.Print i
Next i
Note if Step is positive then your starting number must be lower than you ending number. The following loop will not run because the starting number 20 tells VBA it has already reached the target value 10.
' Will not run as starting number already greater than 10
For i = 20 To 10 Step 1
Debug.Print i
Next i
If Step is negative then the start number must be greater than the end number.
Exit For
Sometimes you may want to leave the loop earlier if a certain condition occurs. For example if you read bad data. You can use Exit For to automatically leave the loop as shown in the following code
For i = 1 To 1000
' If cell is blank then exit for
If Cells(i, 1) = "" Then
MsgBox "Blank Cell found - Data error"
Exit For
Else
Debug.Print Cells(i, 1)
End If
Next i
Using For with a Collection
The for loop can also be used to read items in a collection. In the following example we display the name of all the open workbooks
Dim i As Long
For i = 1 To Workbooks.Count
Debug.Print Workbooks(i).FullName
Next i
Using a Loop with a Loop
Sometimes you may want to use a loop within a loop. An example of this would be where you you want to print the names of the worksheets of each open workbook.
The first loop would go through each workbook. Each time this loop runs it would use a second loop to go through all the worksheets of that workbook. It is actually much easier to do than it sounds. The following code shows how
Sub ListWorksheets()
Dim i As Long, j As Long
' First Loop goes through all workbooks
For i = 1 To Workbooks.Count
' Second loop goes through all the worksheets of workbook(i)
For j = 1 To Workbooks(i).Worksheets.Count
Debug.Print Workbooks(i).Name + ":" + Worksheets(i).Name
Next j
Next i
End Sub
This works as follows
The first loop set i to 1
The second loop then uses the workbook at 1 to go through the worksheets.
The first loop sets i to 2
The second loop then uses the workbook at 2 to go through the worksheets.
and so on
It the next section we will use a For Each loop to perform the same task. You will find the For Each version much easier to read.
The For Each Loop
The For Each loop is used to read items from a collection or an array. We can can use the For Each loop to access all the open workbooks
Dim wk As Workbook
For Each wk In Workbooks
Debug.Print wk.FullName
Next wk
Format of the For Each Loop
For Each in
Next
To create a For Each loop we need a variable of the same type that the collection holds. In the example here we created a variable of type Workbook. If the collection has different types of items we can declare the variable as a variant.
VBA contains a collection called Sheets. This is a collection of sheets of type Worksheet(normal) and Chart(when you move a chart to be a full sheet). To go through this you would declare the variable as a variant. The following code used For Each to print out the name of all the sheets in the current workbook
Dim sh As Variant
For Each sh In ThisWorkbook.Sheets
Debug.Print sh.Name
Next sh
Order of Items
For Each goes through items in one way only. For example if you go through all the worksheets in a workbook it will always go through from left to right. If you go through a range it will start at the lowest cell e.g. Range(A1:A10) will return A1,A2,A3 etc. This means if you want any other order then you need to use the For loop.
Both loops in the following will read the worksheets from left to right.
' Both loops read the worksheets from left to right
Dim wk As Worksheet
For Each wk In ThisWorkbook.Worksheets
Debug.Print wk.Name
Next
Dim i As Long
For i = 1 To ThisWorkbook.Worksheets.Count
Debug.Print ThisWorkbook.Worksheets(i).Name
Next
As you can see the For Each loop is neater to write. However if you want to read the sheets in any other order e.g. right to left then you have to use the for loop.
' Reading the worksheets from right to left
Dim i As Long
For i = ThisWorkbook.Worksheets.Count To 1 Step -1
Debug.Print ThisWorkbook.Worksheets(i).Name
Next
For Each is Read-Only
Another attribute of the For Each loop is that it is Read-Only. You cannot change the value. The following example demonstrates this
Sub UseForEach()
' Create array and add three values
Dim arr() As Variant
arr = Array("A", "B", "C")
Dim s As Variant
' Assigning s does not change the array item
For Each s In arr
' Changes what s is referring to - not value of array item
s = "Z"
Next
' Print items to show the array has remained unchanged
For Each s In arr
Debug.Print s
Next
End Sub
In the first loop we try to assign s to “Z”. When happens is that s is now referring the string “Z” and no longer to the item in the array.
In the second loop we print out the array and you can see that none of the values have changes.
When we use the For Loop we can change the array item. If we change the previous code to use the For Loop you it will change all the array values to “Z”
Sub UsingForWithArray()
' Create array and add three values
Dim arr() As Variant
arr = Array("A", "B", "C")
Dim i As Long
For i = LBound(arr) To UBound(arr)
' Changes value at position to Z
arr(i) = "Z"
Next
' Print items to show the array values have change
For i = LBound(arr) To UBound(arr)
Debug.Print arr(i)
Next
End Sub
Which is Faster? For vs For Each
The For Each loop is widely considered faster than the For loop as it is. However I have been unable to find any concrete sources to back this up 100%. What is important to remember when considering speed is that
The processing power of modern computers means both loops work extremely fast.
You need to have a huge collection for speed to be an issue
Therefore most of the time the loop speed difference will not be an issue for you. If it is then the best thing to do is to try both loops and see which is faster.
Loop Within a Loop
We saw already that you can have a loop inside other loops. In our previous example we used For to read all the worksheets in all the open workbooks. This time we will use For Each to perform the same task
Sub ReadAllWorksheets()
Dim wk As Workbook, sh As Worksheet
' Read each workbook
For Each wk In Workbooks
' Read each worksheet in the wk workbook
For Each sh In wk.Worksheets
' Print workbook name and worksheet name
Debug.Print wk.Name + ": " + sh.Name
Next sh
Next wk
End Sub
As you can see this is a neater way of performing this task than using the For Loop.
This code run as follows:
Get the first Workbook from the Workbooks collection
Go through all the worksheets in this workbook
Print the workbook/worksheet details
Get the next workbooks in the collection
Repeat steps 2 to 3
Continue until no more workbooks are left in the collection
The next loop we will look at is the Do loop. This uses a condition to determine when it completes so first we will take a quick look at conditions.
Conditions
A condition is a statement that evaluates to true or false. They are mostly used with Loops and If statements. When you create a condition you use signs like >,<>,>=,=.
The following are examples of conditions

VBA Conditions
You may have noticed x=5 as a condition. This should not be confused with x=5 when used as an assignment. When equals is used in a condition it means “is the left equal to the right”. The following table demonstrates how equals is used in conditions and assignments

Use equals in a condition vs statement
The Do Loop
The Do loop can be used in four ways and so often causes confusion. There is only a slight difference in each of these four ways.
The difference between the For loop and this loop is that For loop specifies the number of times it will run. The other loops run until a condition is met.
A Do Loop Example
Lets look at a simple example to explain this. Imagine you want to get a series of items from the user. Each time the user enters an item you print it to the immediate window. When the user enters a blank string the macro terminates.
In this case the For loop would not be suitable as you do not know how many items the user will enter. The user could enter the blank string first or hundredth time. For this type of situation you would use a Do loop. The following code shows an example of this
Dim sCommand As String
Do
' Get user input
sCommand = InputBox("Please enter item")
' Print to Immediate Window(Ctrl G to view)
Debug.Print sCommand
Loop Until sCommand = ""
The code enters the loop and runs the code. When it reaches the “Loop Until” line it checks the condition
sCommand = ""
If the condition is true then it exits the loop. If the condition is false it returns to the start of the loop.
Do Loop Until Format
The format of this loop is
Do
Loop Until
You can also place the condition at the start of the loop
Do Until
Loop
The different between these two loops is that the first will run 1 or more times and the second will run 0 or more times. In other words the first will run once before checking the condition so it will always run at least once.
In our example the first loop was used because we need to get a value from the user before we check it. In the following example we use both versions of the loop. The loop will run until the user enters the letter ‘n’
Sub GetInput()
Dim sCommand As String
' Condition at start
Do Until sCommand = "n"
sCommand = InputBox("Please enter item for Loop 1")
Loop
' Condition at end
Do
sCommand = InputBox("Please enter item for Loop 2")
Loop Until sCommand = "n"
End Sub
In this case both loops will behave the same. However if sCommand is equal to ‘n’ before the Do Until loop it will never run. The Do loop will always run at least once.
Sub GetInput2()
Dim sCommand As String
sCommand = "n"
' Loop will not run as command is "n"
Do Until sCommand = "n"
sCommand = InputBox("Please enter item for Loop 1")
Loop
' Loop will still run at least once
Do
sCommand = InputBox("Please enter item for Loop 2")
Loop Until sCommand = "n"
End Sub
Using While instead of Until
You can use While instead of Until in the do loop. This is the same as using Until except for one slight difference – While uses the opposite condition. Until and While are used the same as they are used in English. For example
Leave the clothes on the line Until it rains
Leave the clothes on the line While it does not rain
another example
Stay in bed Until it is light
Stay in bed While it is dark
yet another example
repeat Until the count equals ten
repeat While the count count is less than ten
As you can see – using Until and While is just the opposite way of writing the same condition.
The Do While Loop Format
The only difference in the format of the loop is that you replace Until with While.
Do
Loop While
Do While
Loop
The following code shows the ‘While’ and ‘Until’ loops side by side. As you can see the only difference is the condition is reversed. Note that ‘<>’ means ‘does not equal’.
Sub GetInput()
Dim sCommand As String
' Condition at start
Do Until sCommand = "n"
sCommand = InputBox("Please enter item for Loop 1")
Loop
Do While sCommand <> "n"
sCommand = InputBox("Please enter item for Loop 1")
Loop
' Condition at end
Do
sCommand = InputBox("Please enter item for Loop 2")
Loop Until sCommand = "n"
Do
sCommand = InputBox("Please enter item for Loop 2")
Loop While sCommand <> "n"
End Sub
The first loop says Loop until sCommand equals ‘n’. The second loop says loop while sCommand does not equal ‘n’.
Example: Checking Objects
An example of where Until and While are useful is for checking objects. When an object has not been assigned it has the value Nothing. So when we declare workbook in the following example it has a value of nothing until we assign it to a workbook
Dim wrk As Workbook
The opposite of “Nothing” is “Not Nothing” which can be confusing. Take the following example. Imagine we have two functions called GetFirstWorkbook and GetNextWorkbook which return some workbook objects. The code will print the name of the workbook until the functions do not return a workbook. You can see the sample code here
Dim wrk As Workbook
Set wrk = GetFirstWorkbook()
Do Until wrk Is Nothing
Debug.Print wrk.Name
Set wrk = GetNextWorkbook()
Loop
To write this code using Do While would be more confusing as the condition is Not Is Nothing
Dim wrk As Workbook
Set wrk = GetFirstWorkbook()
Do While Not wrk Is Nothing
Debug.Print wrk.Name
Set wrk = GetNextWorkbook()
Loop
This makes the code clearer and having clear conditions is always a good thing. To be honest this is a very small difference and choosing between While and Until really comes down to a personal choice.
While Wend
This loop is in VBA to make it compatible with older code. Microsoft recommends that you use the Do loops as they are more structured.
From MSDN: “The Do…Loop statement provides a more structured and flexible way to perform looping.”
Format of the While Wend Loop
The While loop has the following format
While
Wend
While Wend vs Do
The different between While and the Do Loop is :
1. While can only have a condition at the start of the loop
2. There is not statement to exit a While loop like Exit For or Exit Do
The condition for the While loop is the same as for the Do While loop. The two loops in the code below perform exactly the same way
Sub GetInput()
Dim sCommand As String
Do While sCommand <> "n"
sCommand = InputBox("Please enter item for Loop 1")
Loop
While sCommand <> "n"
sCommand = InputBox("Please enter item for Loop 2")
Wend
End Sub
Infinite Loop
Even if you have never written code in your life I’m sure you’ve heard the phrase Infinite Loop. This is a loop where the condition will never be met. It normally happens when you forget to update the count.
The following code shows an infinite loop
Dim cnt As Long
cnt = 1
' Do not run - this is an infinite loop
Do While cnt < 5
Loop
In this example cnt is set to 1 but it is never updated. Therefore the condition will never be met – cnt will always be less than 5.
In the following code the cnt is being updated each time so the condition will be met.
Dim cnt As Long
cnt = 1
Do While cnt < 5
cnt = cnt + 1
Loop
As you can see using a For Loop is safer for counting as it automatically updates the count in a loop. The following is the same loop using For.
Dim i As Long
For i = 1 To 4
Next i
This is clearly a better way of doing it. The For Loop sets the initial value, condition and count in one line.
Of course it is possible to have an infinite loop using For – It just takes a bit more effort
Dim i As Long
' DO NOT RUN - Infinite Loop
For i = 1 To 4
' i will never each 4
i = 1
Next i
Dealing With an Infinite Loop
When you have an infinite loop – VBA will not give an error. You code will keep running and the Visual Basic editor will not respond.
In the old days you could break out of a loop by simply pressing Ctrl and Break. Nowadays different Laptops use different key combinations for the same result. It is a good idea to know what this is for your laptop so that if an infinite loop occurs you can stop the code easily.
You can also break out of a loop by killing the process. Press Ctrl+Shift+Esc. Under the Processes tab look for Excel/Microsoft Excel. Right click on this and select “End Process”. This will close Excel and you may lose some work – so it’s much better to use Ctrl+Break or it’s equivalent.
Using Worksheet Functions Instead of Loops
Sometimes you can use a worksheet function instead of using a loop. For example, imagine you wanted to add the values in a list of cells. You could do this using a loop but it would be more efficient to use the worksheet function Sum. This is quicker and saves you a lot of code.
It is very easy to use the Worksheet functions. The following is an example of using Sum and Count. Remember that in VBA the argument they take is a range object and not a string. In other words you must use Range(“A1:A10″) rather than “A1:A10″.
Sub WorksheetFunctions()
Debug.Print WorksheetFunction.Sum(Range("A1:A10"))
Debug.Print WorksheetFunction.Count(Range("A1:A10"))
End Sub
The following examples uses a loop to perform the same action. As you can see it is a much longer way of achieving the same goal
Sub SumWithLoop()
Dim total As Long, count As Long
Dim rg As Range
For Each rg In Range("A1:A10")
' Total
total = total + rg
' Count
If rg <> "" Then
count = count + 1
End If
Next rg
Debug.Print total
Debug.Print count
End Sub
Summary
There are four types of loops in VBA:
For Next
For Each Next
Do Loop
While Wend
The For Loop is the most commonly used in VBA
The For loop is flexible as you can determine the size and order to read through.
The For Each is used to read through a collection. You cannot change the order. It is neater to write than a For Loop.
For Each is considered faster than the For Loop but with modern processing power this not an issue unless you have extremely large collections.
For Each is read only – you cannot change the value of the item
For can read and write – you can change the value of the item
The While Wend loop is obsolete and you can use the Do Loop instead.
The Do loop can be used 4 ways. With a While/Until condition at the start or end of the loop.
While and Until use opposite conditions in a Do loop.
Infinite Loops occur if your loop condition will never be met
Sometimes using a worksheet function is more efficient than using a loop
I hope you enjoyed this post and found it beneficial. You may also find the posts about Arrays or Cells very useful.