In Excel: Write If condition Then on its own line, put the action underneath, add ElseIf and Else branches as needed, and close the block with End If. Excel for the web cannot create, run, or edit VBA macros. Open the workbook in the Excel desktop app to work with macros.
On this page8
VBA macro: VBA If, ElseIf and Else
Sub GradeScores()
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim score As Double
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
If Not IsNumeric(ws.Cells(i, 1).Value) Then
ws.Cells(i, 2).Value = "n/a"
Else
score = CDbl(ws.Cells(i, 1).Value)
If score >= 90 Then
ws.Cells(i, 2).Value = "A"
ElseIf score >= 80 Then
ws.Cells(i, 2).Value = "B"
Else
ws.Cells(i, 2).Value = "C"
End If
End If
Next i
End SubThe IsNumeric guard runs first so CDbl never receives text — a type-mismatch there is the usual cause of error 13 in grading code. Conditions are tested top to bottom and the first true branch wins, so >= 90 must precede >= 80.
How to run this macro
- Press Alt + F11 to open the VBA editor.
- Insert > Module.
- Paste the code above.
- Press
F5, or close the editor and run it from Developer > Macros. - Save the file as .xlsm so the macro is kept.
Write If followed by the condition and the word Then, and press Enter.
Put each branch's actions on their own indented lines beneath it.
Add ElseIf condition Then for further cases, ordering them from most specific to most general.
Add a bare Else as the catch-all for everything unmatched — usually worth having even if only to flag surprises.
Close the block with End If, and run it against data containing an edge case as well as a normal value.
What this does
An If block is how a macro makes a decision. The block form spans several lines — If condition Then, the action, optional ElseIf and Else branches, then End If — and it is the form worth defaulting to, because it accepts multiple statements per branch and stays readable. There is also a single-line form, If x > 0 Then y = 1, which needs no End If but silently disallows anything else on the same line; mixing the two up is a common source of "Block If without End If". Branches are tested strictly top to bottom and the first true one wins, so ordering matters: putting a wide condition above a narrow one makes the narrow branch unreachable. Compound tests use And and Or, which in VBA evaluate both sides regardless of the first result — unlike many other languages, there is no short-circuiting, so a second test that would error on its own cannot be guarded by the first. A macro runs in the desktop app's VBA environment, not in the cell grid: the workbook has to be saved in a macro-enabled format such as .xlsm to keep the code, and your macro security settings — or a file that arrived from the internet — can block it until you trust it. Excel for the web cannot run VBA at all. For “excel vba if then”, the reliable version is a short checking loop, not just the first command that appears to work. Run it on a deliberately small range first, watch how the affected cells change, and only then apply the same setup to the full sheet. When this is a ribbon command, the selection matters more than the button: confirm the range, apply the command, then spot-check the output before saving. That is what makes a workflow that saves repeating the same clicks every week useful in real work: repeatable, auditable, and not dependent on memory or luck.
A worked example
Column A holds exam scores and column B should hold a letter grade. Sub GradeScores() reads down to the last used row, checks each value is numeric, and applies three thresholds. The IsNumeric test comes first for a reason: a blank or a stray "absent" would make CDbl raise a type mismatch, and one bad cell stops the whole run. Note the branch order — 90 is also greater than 80, so if the >= 80 test came first every A would be graded B. To combine conditions, write If score >= 90 And attended = True Then. Because VBA evaluates both sides, If Not rng Is Nothing And rng.Value > 0 Then still errors when rng is Nothing; the safe form is nested Ifs, with the object check on the outside. A macro without conditions can only replay a fixed sequence — the If block is what lets it react to what is actually in the data. It is also where the subtle bugs live: branch order and the absence of short-circuit evaluation both produce code that runs cleanly and quietly returns the wrong answer. If the macro will be shared, add a comment at the top saying what it changes and which sheet it expects, and keep the workbook as .xlsm — saving it as .xlsx removes the code.
In Google Sheets
Google Sheets does not run VBA. A macro written for Excel has to be rewritten in Google Apps Script (Extensions ▸ Apps Script), and an .xlsm file converted to Sheets keeps its cells but drops the code. Keep this page bookmarked for the next time the same question comes up. Better still, repeat the steps once in your own workbook — doing it yourself is what turns a copied answer into something you remember. The short version of “excel vba if then”: paste the code, keep the workbook macro-enabled, trust the file only if you know where it came from, and test on a copy. Code that refers to the active sheet acts on whichever sheet is active, so check that before you run it.
Common mistakes
- Ordering conditions from general to specific. The first true branch wins, so If score >= 80 placed above If score >= 90 makes the A branch dead code that never executes.
- Expecting And and Or to short-circuit. VBA evaluates both operands every time, so a null-check joined by And does not protect the test after it — nest the Ifs instead.
- Comparing to an empty cell with = "" and assuming it means empty. A cell holding a formula that returns "" passes that test while IsEmpty returns False; decide which of the two you actually mean.
- Using a single-line If and then trying to add a second statement to it. The line silently does something else, or fails to compile — switch to the block form the moment a branch needs more than one action.
- Testing text with = and being surprised by case. "Yes" = "yes" is False under the default Option Compare Binary; wrap both sides in LCase or set Option Compare Text at the top of the module.
Frequently asked questions
What is the difference between ElseIf and a nested If?
ElseIf continues the same block, so exactly one branch runs and there is a single End If. A nested If starts a new block inside a branch and needs its own End If. Use ElseIf for alternatives at the same level, nesting for a test that only makes sense after another passed.
Do I always need End If?
Only for the block form. The single-line version, If x > 0 Then y = 1, is self-closing — but it holds one statement, and any attempt to extend it is what produces the "Block If without End If" error.
When should I use Select Case instead?
When one value is being compared against many possible matches. A chain of more than three or four ElseIf tests against the same variable is almost always clearer as Select Case.
How do I test several conditions at once?
Join them with And or Or: If a > 0 And b > 0 Then. Both sides are always evaluated, so if one could raise an error on its own, nest the tests rather than combining them.