Tested on: Excel 365 v2509 · Excel 2021 · Excel 2019 · last verified 2026-06-06
TL;DR — MsgBox shows the user a short message and a few buttons, then tells you which button they clicked. Use it two ways — to announce something, and to ask a yes/no question:
Sub MsgBoxBasics()
' 1. Announce — fire and forget (a statement, NO brackets)
MsgBox "Import finished.", vbInformation, "Done"
' 2. Ask — capture the answer (a function, brackets REQUIRED)
Dim answer As VbMsgBoxResult
answer = MsgBox("Delete the selected row?", vbYesNo + vbQuestion, "Confirm")
If answer = vbYes Then
Selection.EntireRow.Delete
End If
End Sub
That single difference — brackets or no brackets — is behind almost every "Compile error: Expected: end of statement" people hit with MsgBox. The rest of this guide is built around it.
The mental model: MsgBox is an intercom, not a keyboard
Picture an intercom on a wall. You can broadcast one line to whoever's listening, and you can offer them a small set of buttons to answer with — Yes, No, Cancel, Retry. What you can not do is hear them type a sentence back. The moment you need free-form input — a filename, a number, a date — you've outgrown MsgBox and want InputBox or a UserForm.
So MsgBox does exactly two jobs well: tell the user something, or ask a closed question and branch on the click. Keep it to those and it never fights you.
The one rule: statement form vs function form
MsgBox has two faces, and which one you're using decides whether brackets are legal.
Statement form — you only want to show the message and don't care what's clicked:
MsgBox "Saved!" ' ✅
MsgBox "Saved!", vbInformation, "Status" ' ✅ arguments separated by commas, NO brackets
MsgBox ("Saved!", vbInformation) ' ❌ Compile error: Expected: end of statement
That last line fails because VBA reads ( … ) after a statement as "evaluate this one expression", and "Saved!", vbInformation isn't one expression — it's an argument list. Brackets only belong on a function call.
Function form — you want the return value, so you assign it, and now brackets are mandatory:
Dim r As VbMsgBoxResult
r = MsgBox("Overwrite the file?", vbYesNo) ' ✅ using the result → brackets required
The rule in one sentence: using the return value → brackets; ignoring it → no brackets. Internalise that and the syntax error disappears for good.
Read the answer by name, never by number
MsgBox returns an integer, but never compare it to a raw number. vbYes happens to be 6 — write vbYes, not 6. The named constants read like English and survive anyone (including future-you) reading the macro:
Select Case MsgBox("Save changes before closing?", vbYesNoCancel + vbExclamation)
Case vbYes: ThisWorkbook.Save
Case vbNo: ' close without saving — do nothing
Case vbCancel: Exit Sub ' user backed out → stop the whole macro
End Select
This three-way vbYesNoCancel is the pattern worth memorising: Cancel = "I changed my mind, stop everything." Honour it with Exit Sub, and your users will trust the macro.
Buttons and icons combine with +
The second argument packs two independent choices — which buttons and which icon — into one number, so you add them:
MsgBox "Disk is almost full.", vbOKOnly + vbCritical ' red ✖ icon
MsgBox "Run the overnight job now?", vbYesNo + vbQuestion ' blue ? icon
MsgBox "Network glitch — retry?", vbRetryCancel + vbExclamation ' yellow ! icon
They live in different "slots" of the number, which is why + works cleanly. Want a non-default highlighted button (so a careless Enter doesn't delete anything)? Add vbDefaultButton2 to make the second button the default.
Drop a variable into the message
A constant string is rare in real macros — you almost always want to report a count, a name, a result. Concatenate with &, and use vbNewLine to stack lines:
Dim n As Long
n = WorksheetFunction.CountA(Range("A:A")) - 1
MsgBox "Processed " & n & " rows." & vbNewLine & _
"Finished at " & Format(Now, "hh:mm:ss"), vbInformation, "Report"
That & (not +) for joining text, and vbNewLine for the break, are the two things people forget most.
Don't use MsgBox to debug
The most common misuse: sprinkling MsgBox x through a loop to "see the value." On 500 rows that's 500 clicks — and the macro is frozen on each one. MsgBox is modal: it blocks until the user clicks, by design, because it exists to make a human stop and decide.
For watching values while you develop, use the Immediate window instead:
Debug.Print "row " & i & " = " & cell.Value ' Ctrl+G to read it, zero clicks, no blocking
Rule of thumb: MsgBox is a decision gate for the end user; Debug.Print is the developer's print. Mixing them up is what makes macros feel clunky.
Common MsgBox mistakes (and the fix)
| Symptom | Cause | Fix |
|---|---|---|
| "Expected: end of statement" | Brackets on the statement form: MsgBox ("Hi", vbYesNo) |
Drop the brackets, or assign the result: r = MsgBox("Hi", vbYesNo) |
| Answer never matches | Comparing to 6 / 7 magic numbers |
Compare to vbYes / vbNo constants |
| Macro keeps running after Cancel | Only checked vbYes, ignored vbCancel |
Add Case vbCancel: Exit Sub |
| Title shows in the wrong spot | Argument order is prompt, buttons, title |
Title is the third arg: MsgBox "msg", vbOKOnly, "Title" |
| Text and number jammed together | Used + to join, which adds or errors |
Join with &: "Total " & n |
| Buttons + icon don't both appear | Used a comma between them | Combine with +: vbYesNo + vbQuestion |
Skip the dialog plumbing — just describe the rule
A MsgBox confirmation is fine for one decision. But when the logic behind the decision is the hard part — "before deleting, check column D is empty and the date is in the past" — wiring that up in VBA is the real work. ExcelMaster Agent lets you say the rule in plain English — "delete rows where status is blank and the due date has passed, but ask me first" — and it writes the guard, the confirmation, and the delete for you. Try it free →
Related guides
- VBA InputBox in Excel — The Two InputBoxes, and When to Use Each
- VBA UserForm in Excel — Build a Real Data-Entry Form
- VBA If Then Else in Excel — Conditions Done Right
- VBA For Loop in Excel — 8 Real-World Examples
FAQ
What is MsgBox in VBA?
MsgBox is a built-in VBA function that displays a small dialog box with a message and one or more buttons, then returns a value telling you which button the user clicked. Use it to notify the user or to ask a simple Yes/No question.
Why do I get "Expected: end of statement" with MsgBox?
Because you put brackets around the arguments while using MsgBox as a statement, e.g. MsgBox ("Hi", vbYesNo). Brackets are only allowed when you capture the return value: answer = MsgBox("Hi", vbYesNo). Without a return value, drop the brackets: MsgBox "Hi", vbYesNo.
How do I make a Yes/No message box in VBA?
Call MsgBox as a function with the vbYesNo constant and read the result: If MsgBox("Continue?", vbYesNo) = vbYes Then …. Add vbQuestion for the question-mark icon: vbYesNo + vbQuestion.
How do I show an icon in a VBA MsgBox?
Add an icon constant to the buttons argument with +: vbCritical (red ✖), vbExclamation (yellow !), vbQuestion (blue ?), or vbInformation (blue i). Example: MsgBox "Done", vbOKOnly + vbInformation.
How do I put a variable in a MsgBox?
Join the text and the variable with &: MsgBox "Total: " & total. Use vbNewLine to start a new line inside the message.
What's the difference between MsgBox and InputBox?
MsgBox only outputs a message and returns which button was clicked — it can't accept typed text. InputBox prompts the user to type a value and returns what they entered. Use MsgBox to inform or confirm, InputBox to collect input.
