NexusCS

VBA

Languages
Quick reference for VBA (Visual Basic for Applications) - the programming language for Microsoft Office automation, macros, and Excel scripting.
excel
office
automation
macro

Getting started

Introduction

VBA (Visual Basic for Applications) is a programming language for Office automation, primarily used in Excel macros.

First Macro

Sub HelloWorld()
    MsgBox "Hello, World!"
End Sub

Run with F5 in VBA Editor or assign to button.

Quick Example

Sub FormatReport()
    ' Select data range
    Range("A1:D10").Select

    ' Apply formatting
    Selection.Font.Bold = True
    Selection.Interior.Color = RGB(200, 220, 255)

    ' Auto-fit columns
    Columns("A:D").AutoFit
End Sub

Procedures

Sub Procedures

Sub MyProcedure()
    ' Code here (no return value)
End Sub

Execute with Call MyProcedure() or MyProcedure.

Sub with Parameters

Sub Greet(name As String)
    MsgBox "Hello, " & name
End Sub

' Call it
Call Greet("Alice")

Function Procedures

Function AddNumbers(x As Integer, y As Integer) As Integer
    AddNumbers = x + y
End Function

' Use it
Dim result As Integer
result = AddNumbers(5, 3)

Function Return Types

Function GetWorksheetName() As String
    GetWorksheetName = ActiveSheet.Name
End Function

Function IsWeekend(dt As Date) As Boolean
    IsWeekend = (Weekday(dt) = 1 Or Weekday(dt) = 7)
End Function

Variables & Data Types

Variable Declaration

Dim name As String
Dim count As Integer
Dim price As Double
Dim isActive As Boolean

Common Data Types

Type Storage Range
Integer 2 bytes -32,768 to 32,767
Long 4 bytes -2 billion to 2 billion
Single 4 bytes Floating-point
Double 8 bytes Floating-point
Currency 8 bytes Money calculations
String Variable Text
Boolean 2 bytes True/False
Date 8 bytes Date and time
Variant Variable Any type
Object 4 bytes Object references

Constants

Const TAX_RATE As Double = 0.15
Const COMPANY_NAME As String = "Acme Corp"

Public Const MAX_ROWS As Long = 1000

Variable Scope

' Module-level (top of module)
Dim moduleVar As String

' Procedure-level
Sub MyProcedure()
    Dim localVar As Integer
End Sub

' Public (accessible from other modules)
Public Shared globalVar As Boolean

Conditional Statements

If...Then...Else (Single-line)

If x > 10 Then MsgBox "Large"

If y = 0 Then Exit Sub

If...Then...Else (Block)

If score >= 90 Then
    grade = "A"
ElseIf score >= 80 Then
    grade = "B"
ElseIf score >= 70 Then
    grade = "C"
Else
    grade = "F"
End If

Comparison Operators

=   ' Equal
<>  ' Not equal
>   ' Greater than
<   ' Less than
>=  ' Greater or equal
<=  ' Less or equal

Logical Operators

If age >= 18 And hasLicense = True Then
    MsgBox "Can drive"
End If

If day = "Saturday" Or day = "Sunday" Then
    MsgBox "Weekend"
End If

If Not isEmpty Then
    ProcessData
End If

Select Case

Select Case dayOfWeek
    Case "Monday", "Tuesday", "Wednesday"
        MsgBox "Weekday"
    Case "Thursday", "Friday"
        MsgBox "Almost weekend"
    Case "Saturday", "Sunday"
        MsgBox "Weekend!"
    Case Else
        MsgBox "Invalid day"
End Select

Select Case with Ranges

Select Case score
    Case Is >= 90
        grade = "A"
    Case 80 To 89
        grade = "B"
    Case 70 To 79
        grade = "C"
    Case Else
        grade = "F"
End Select

Loops

For...Next Loop

Dim i As Integer
For i = 1 To 10
    Cells(i, 1).Value = i
Next i

For...Next with Step

' Count by 2s
For i = 0 To 10 Step 2
    Debug.Print i
Next i

' Count backwards
For i = 10 To 1 Step -1
    Debug.Print i
Next i

For Each...Next

Dim cell As Range
For Each cell In Range("A1:A10")
    cell.Value = cell.Value * 2
Next cell

For Each with Collections

Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
    Debug.Print ws.Name
Next ws

Dim wb As Workbook
For Each wb In Application.Workbooks
    Debug.Print wb.Name
Next wb

Do While Loop

Dim i As Integer
i = 1
Do While Cells(i, 1).Value <> ""
    Cells(i, 2).Value = Cells(i, 1).Value * 2
    i = i + 1
Loop

Do Until Loop

Dim row As Integer
row = 1
Do Until IsEmpty(Cells(row, 1))
    row = row + 1
Loop
MsgBox "Last row: " & row - 1

Exit Loop Early

For i = 1 To 100
    If Cells(i, 1).Value = "STOP" Then
        Exit For
    End If
    ProcessRow i
Next i

Do While True
    If condition Then Exit Do
Loop

Arrays

Static Arrays

Dim names(5) As String
names(0) = "Alice"
names(1) = "Bob"

Dim matrix(3, 3) As Integer
matrix(1, 1) = 10

Dynamic Arrays

Dim items() As String
ReDim items(10)

' Resize and preserve data
ReDim Preserve items(20)

Array Initialization

Dim colors As Variant
colors = Array("Red", "Green", "Blue")

Dim numbers As Variant
numbers = Array(1, 2, 3, 4, 5)

' Access elements
MsgBox colors(0)  ' "Red"

Array Bounds

Dim arr(1 To 10) As Integer

' Get bounds
Dim lower As Integer
Dim upper As Integer
lower = LBound(arr)  ' 1
upper = UBound(arr)  ' 10

' Loop through array
For i = LBound(arr) To UBound(arr)
    arr(i) = i * 2
Next i

Multi-dimensional Arrays

Dim sales(12, 4) As Double  ' 12 months, 4 quarters

sales(1, 1) = 1000.50
sales(1, 2) = 1200.75

' Loop through 2D array
For month = 1 To 12
    For quarter = 1 To 4
        Debug.Print sales(month, quarter)
    Next quarter
Next month

String Functions

String Extraction

Dim text As String
text = "Hello World"

' Mid(string, start, length)
Mid(text, 1, 5)      ' "Hello"
Mid(text, 7)         ' "World"

' Left(string, length)
Left(text, 5)        ' "Hello"

' Right(string, length)
Right(text, 5)       ' "World"

String Information

' Length
Len("Hello")         ' 5

' Find substring position
InStr("Hello World", "World")  ' 7
InStr("Hello World", "xyz")    ' 0 (not found)

' Case-insensitive search
InStr(1, "Hello", "HELLO", vbTextCompare)  ' 1

String Manipulation

' Replace
Replace("Hello World", "World", "VBA")  ' "Hello VBA"

' Trim whitespace
Trim("  Hello  ")    ' "Hello"
LTrim("  Hello")     ' "Hello"
RTrim("Hello  ")     ' "Hello"

' Case conversion
UCase("hello")       ' "HELLO"
LCase("HELLO")       ' "hello"

String Comparison

' StrComp(string1, string2, compare)
StrComp("ABC", "abc", vbTextCompare)  ' 0 (equal)
StrComp("ABC", "abc", vbBinaryCompare) ' -1 (not equal)

' Like operator (pattern matching)
"Hello" Like "H*"    ' True
"Test123" Like "Test###"  ' True

String Concatenation

' Using &
name = "John"
greeting = "Hello, " & name & "!"

' Using + (not recommended)
message = "Line 1" + vbCrLf + "Line 2"

Excel Workbook Object

Access Workbooks

' Active workbook
Dim wb As Workbook
Set wb = ActiveWorkbook

' This workbook (where code runs)
Set wb = ThisWorkbook

' By index
Set wb = Workbooks(1)

' By name
Set wb = Workbooks("Sales.xlsx")

Workbook Operations

' Open workbook
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Data\Report.xlsx")

' Create new workbook
Set wb = Workbooks.Add

' Save
ActiveWorkbook.Save

' Save As
ActiveWorkbook.SaveAs "C:\Data\NewFile.xlsx"

' Close
wb.Close SaveChanges:=True

Workbook Properties

' Get workbook name
Debug.Print ActiveWorkbook.Name

' Get full path
Debug.Print ActiveWorkbook.FullName

' Get path (folder)
Debug.Print ActiveWorkbook.Path

' Check if saved
If ActiveWorkbook.Saved = False Then
    ActiveWorkbook.Save
End If

Count Workbooks

Dim count As Integer
count = Workbooks.Count

MsgBox "Open workbooks: " & count

Excel Worksheet Object

Access Worksheets

' Active sheet
Dim ws As Worksheet
Set ws = ActiveSheet

' By index
Set ws = Worksheets(1)

' By name
Set ws = Worksheets("Sales")

' Short syntax
Set ws = Sheets("Data")

Worksheet Operations

' Add new worksheet
Dim newSheet As Worksheet
Set newSheet = Worksheets.Add

' Add with name
Set newSheet = Worksheets.Add
newSheet.Name = "Report"

' Delete worksheet
Application.DisplayAlerts = False
Worksheets("OldData").Delete
Application.DisplayAlerts = True

' Copy worksheet
Worksheets("Template").Copy After:=Worksheets(1)

Worksheet Properties

' Rename
Worksheets(1).Name = "Summary"

' Visibility
Worksheets("Hidden").Visible = xlSheetHidden
Worksheets("Hidden").Visible = xlSheetVisible

' Protect/Unprotect
ActiveSheet.Protect Password:="secret"
ActiveSheet.Unprotect Password:="secret"

' Tab color
Worksheets("Sales").Tab.Color = RGB(255, 0, 0)

Count Worksheets

Dim count As Integer
count = ThisWorkbook.Worksheets.Count

MsgBox "Total sheets: " & count

Excel Range Object

Access Ranges

' By address
Range("A1").Value = 100
Range("A1:C10").Select

' By Cells(row, col)
Cells(1, 1).Value = "Header"
Cells(5, 2).Value = 999

' Combined
Range(Cells(1, 1), Cells(10, 5)).Select

' Named range
Range("SalesData").Select

Range Properties

' Get/Set value
Dim val As Variant
val = Range("A1").Value
Range("B1").Value = val * 2

' Formula
Range("C1").Formula = "=A1+B1"
Range("C1").FormulaR1C1 = "=RC[-2]+RC[-1]"

' Text
Range("A1").Text  ' Read-only formatted text

Range Selection

' Select range
Range("A1:D10").Select

' Entire row/column
Rows(1).Select
Columns("A").Select

' Current region (contiguous data)
Range("A1").CurrentRegion.Select

' Used range
ActiveSheet.UsedRange.Select

Range Formatting

With Range("A1:D1")
    .Font.Bold = True
    .Font.Size = 14
    .Font.Color = RGB(255, 0, 0)
    .Interior.Color = RGB(200, 200, 200)
    .HorizontalAlignment = xlCenter
End With

' Number format
Range("A1").NumberFormat = "$#,##0.00"
Range("B1").NumberFormat = "0.00%"
Range("C1").NumberFormat = "mm/dd/yyyy"

Range Methods

' Copy/Paste
Range("A1:A10").Copy Destination:=Range("B1")

' Clear
Range("A1:D10").Clear          ' Everything
Range("A1:D10").ClearContents  ' Values only
Range("A1:D10").ClearFormats   ' Formats only

' Delete/Insert
Range("A1:A10").Delete Shift:=xlUp
Range("A1").EntireRow.Insert

' AutoFit
Columns("A:D").AutoFit
Rows("1:10").AutoFit

Find Last Row/Column

' Last row with data in column A
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

' Last column with data in row 1
Dim lastCol As Long
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

MsgBox "Last row: " & lastRow

Message Boxes & Input

Basic Message Box

MsgBox "Operation complete!"

MsgBox "Error: File not found", vbCritical

MsgBox "Data saved successfully", vbInformation, "Success"

Message Box Buttons

Dim result As VbMsgBoxResult

result = MsgBox("Save changes?", vbYesNo)
If result = vbYes Then
    SaveData
End If

result = MsgBox("Delete?", vbYesNoCancel, "Confirm")
Select Case result
    Case vbYes
        DeleteData
    Case vbNo
        ' Do nothing
    Case vbCancel
        Exit Sub
End Select

Message Box Icons

' vbInformation (blue i)
MsgBox "Info", vbInformation

' vbExclamation (yellow !)
MsgBox "Warning", vbExclamation

' vbCritical (red X)
MsgBox "Error", vbCritical

' vbQuestion (blue ?)
MsgBox "Continue?", vbQuestion

Input Box

Dim name As String
name = InputBox("Enter your name:", "User Input")

If name <> "" Then
    MsgBox "Hello, " & name
End If

' With default value
Dim age As String
age = InputBox("Enter age:", "Age", "25")

Application Input Box

' Select range
Dim rng As Range
Set rng = Application.InputBox("Select range:", Type:=8)

If Not rng Is Nothing Then
    rng.Interior.Color = RGB(255, 255, 0)
End If

Error Handling

On Error GoTo

Sub ErrorHandlingExample()
    On Error GoTo ErrorHandler

    ' Code that might fail
    Dim wb As Workbook
    Set wb = Workbooks.Open("C:\missing.xlsx")

    Exit Sub

ErrorHandler:
    MsgBox "Error: " & Err.Description, vbCritical
    Err.Clear
End Sub

On Error Resume Next

Sub IgnoreErrors()
    On Error Resume Next

    ' Try to delete (ignore if doesn't exist)
    Worksheets("TempData").Delete

    On Error GoTo 0  ' Turn off error handling
End Sub

Error Object

Sub DetailedError()
    On Error GoTo ErrorHandler

    ' Risky code
    Dim x As Integer
    x = 10 / 0

    Exit Sub

ErrorHandler:
    MsgBox "Error #" & Err.Number & vbCrLf & _
           "Description: " & Err.Description & vbCrLf & _
           "Source: " & Err.Source
    Err.Clear
End Sub

Custom Error Raising

Sub ValidateInput(age As Integer)
    If age < 0 Or age > 150 Then
        Err.Raise Number:=vbObjectError + 1, _
                  Description:="Invalid age"
    End If
End Sub

Common Patterns

Loop Through Rows

Sub ProcessRows()
    Dim i As Long
    Dim lastRow As Long

    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow  ' Skip header
        If Cells(i, 1).Value > 100 Then
            Cells(i, 3).Value = "High"
        Else
            Cells(i, 3).Value = "Low"
        End If
    Next i
End Sub

Work with Multiple Sheets

Sub ConsolidateSheets()
    Dim ws As Worksheet
    Dim masterRow As Long

    masterRow = 2  ' Start after header

    For Each ws In ThisWorkbook.Worksheets
        If ws.Name <> "Summary" Then
            Dim lastRow As Long
            lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row

            ws.Range("A2:D" & lastRow).Copy _
                Worksheets("Summary").Cells(masterRow, 1)

            masterRow = masterRow + (lastRow - 1)
        End If
    Next ws
End Sub

Find and Replace

Sub FindAndReplace()
    Dim ws As Worksheet

    For Each ws In ThisWorkbook.Worksheets
        ws.Cells.Replace What:="old", _
                        Replacement:="new", _
                        LookAt:=xlWhole, _
                        MatchCase:=False
    Next ws
End Sub

Create Table/List

Sub CreateDataTable()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim tbl As ListObject

    Set ws = ActiveSheet
    lastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row

    ' Convert range to table
    Set tbl = ws.ListObjects.Add(xlSrcRange, _
                ws.Range("A1:D" & lastRow), , xlYes)

    tbl.Name = "SalesData"
    tbl.TableStyle = "TableStyleMedium2"
End Sub

Export to CSV

Sub ExportToCSV()
    Dim filePath As String

    filePath = ThisWorkbook.Path & "\export.csv"

    ActiveSheet.Copy
    With ActiveWorkbook
        .SaveAs Filename:=filePath, FileFormat:=xlCSV
        .Close SaveChanges:=False
    End With
End Sub

Progress Bar

Sub ShowProgress()
    Dim i As Long
    Dim total As Long

    total = 1000

    For i = 1 To total
        ' Update status bar
        Application.StatusBar = "Processing: " & _
            Format(i / total, "0%")

        ' Your code here
        DoEvents  ' Keep Excel responsive
    Next i

    Application.StatusBar = False  ' Clear status
End Sub

Debugging

Debug.Print

Sub DebugExample()
    Dim x As Integer
    x = 10

    Debug.Print "Value of x: " & x
    Debug.Print "Workbook: " & ThisWorkbook.Name
End Sub

View output in Immediate Window (Ctrl+G).

Breakpoints

Sub StepThrough()
    Dim i As Integer

    For i = 1 To 10
        ' Click left margin to set breakpoint
        Cells(i, 1).Value = i * 2
    Next i
End Sub

Press F8 to step through code, F5 to continue.

Watch Window

Sub WatchVariables()
    Dim total As Double
    Dim count As Integer

    ' Add watches in VBA Editor: View > Watch Window
    total = 0
    For count = 1 To 100
        total = total + count
    Next count
End Sub

Immediate Window

' Type in Immediate Window (Ctrl+G):
? Cells(1, 1).Value
? ActiveSheet.Name
? Worksheets.Count

' Execute statements:
Cells(1, 1).Value = 100
Range("A1:A10").ClearContents

Best Practices

Turn Off Screen Updating

Sub FastMacro()
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    ' Your code here

    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub

Use With Statements

' Bad
Range("A1").Font.Bold = True
Range("A1").Font.Size = 14
Range("A1").Font.Color = RGB(255, 0, 0)

' Good
With Range("A1").Font
    .Bold = True
    .Size = 14
    .Color = RGB(255, 0, 0)
End With

Qualify Objects

' Bad (implicit ActiveSheet)
Range("A1").Value = 100

' Good (explicit reference)
ThisWorkbook.Worksheets("Data").Range("A1").Value = 100

Use Constants

' Bad
If Cells(i, 5).Value > 1000 Then

' Good
Const COL_SALES As Integer = 5
Const THRESHOLD As Long = 1000

If Cells(i, COL_SALES).Value > THRESHOLD Then

Clean Up Objects

Sub CleanupExample()
    Dim wb As Workbook
    Dim ws As Worksheet

    Set wb = Workbooks.Open("data.xlsx")
    Set ws = wb.Worksheets(1)

    ' Use objects

    ' Cleanup
    wb.Close SaveChanges:=False
    Set ws = Nothing
    Set wb = Nothing
End Sub

Keyboard Shortcuts

VBA Editor

Shortcut Action
Alt+F11 Open VBA Editor
F5 Run macro
F8 Step into code
Shift+F8 Step over
Ctrl+Break Stop execution
F9 Toggle breakpoint
Ctrl+G Immediate window
F2 Object Browser

Code Editing

Shortcut Action
Ctrl+Space Auto-complete
Ctrl+Y Delete line
Tab Indent
Shift+Tab Un-indent
Ctrl+F Find
Ctrl+H Replace

Also see