TL;DR — A
CheckBoxis a yes/no toggle: read.Valueas aBoolean,TrueorFalse, withIf CheckBox1.Value Then .... Two things surprise people.TripleState = Truegives.Valuea third state,Null, and thenIf CheckBox1.Valueraises a Type mismatch. And its cousin theOptionButton(a radio button) is exclusive by container: every option button on the same form is one group, so you separate independent groups with aFrame.CheckBox= independent toggles;OptionButton-in-a-Frame= pick exactly one.
' Reading checkboxes is as simple as VBA gets
Private Sub cmdSave_Click()
If chkEmail.Value Then Range("B1").Value = "Email opt-in"
If chkSMS.Value Then Range("B2").Value = "SMS opt-in"
End Sub
A CheckBox is a control on a UserForm, and it is the friendliest one to read: its
.Value is a plain Boolean. That simplicity is exactly why the two exceptions below catch people out —
you stop expecting the control to do anything clever, and then TripleState or an ungrouped radio set
bites.
What you'll learn
- Reading a
CheckBoxas aBoolean, the simplest control on any form - The
TripleStatetrap: a third.ValueofNullthat makesIf CheckBox1.Valuefail - Why
OptionButtongroups are decided by their container, not by naming - How a
Frame(orGroupName) keeps two radio groups from fighting each other - The judgment call:
CheckBoxfor independent yes/nos,OptionButtonfor one-of-many - Why you should never fake a radio group out of checkboxes
The mental model: a checkbox is a Boolean you can see
There is almost nothing to a CheckBox. It is a Boolean with a label on it:
CheckBox1.Value ' True when ticked, False when clear
Read it with an If, write it to toggle the tick, and you are done. This is the cleanest control-to-code
mapping on a form, and for a set of independent yes/no options — email opt-in, SMS opt-in, include
totals — it is exactly right. Each checkbox stands alone; ticking one has no effect on any other. Hold on
to that "independent" idea, because it is the line between a CheckBox and an OptionButton.
The TripleState trap: when .Value can be Null
A CheckBox has a TripleState property. Leave it False (the default) and .Value is only ever True
or False. Set it True and the control gains a third state — a greyed, indeterminate tick — whose
.Value is Null, not False:
' With TripleState = True, this line can blow up
If CheckBox1.Value Then ... ' Null in an If raises run-time error 13, Type mismatch
If Null Then is a Type mismatch (run-time error 13), because Null is neither True nor False. So
if you turn on TripleState, you must test the three states explicitly:
If IsNull(CheckBox1.Value) Then
' indeterminate - neither on nor off
ElseIf CheckBox1.Value Then
' ticked
Else
' clear
End If
The practical advice: do not enable TripleState unless you genuinely need an indeterminate state.
Most forms do not, and every one that leaves it off can read .Value with a plain If.
OptionButton: the same simplicity, one exclusive answer
An OptionButton (a radio button) reads exactly like a CheckBox — .Value is True for the selected
one — but its whole point is that only one in a group can be True at a time. Selecting one clears
the others. You read a group by finding the one that is on:
Dim shipping As String
If optStandard.Value Then shipping = "Standard"
If optExpress.Value Then shipping = "Express"
If optOvernight.Value Then shipping = "Overnight"
That is the right control when the answer is one of several — shipping speed, a payment method, a size. Where it goes wrong is grouping.
The grouping trap: option buttons are exclusive by container
This is the mistake that produces "selecting one radio deselects a button in a totally unrelated group."
OptionButton exclusivity is decided by the container, not by names or intent. Every option button
placed directly on the UserForm belongs to one group — so two separate radio questions on the same
form fight each other. The fix is to give each set its own container, a Frame:
UserForm
Frame "Shipping" <- one exclusive group
optStandard
optExpress
optOvernight
Frame "Payment" <- a separate, independent group
optCard
optInvoice
Drop each cluster of option buttons inside its own Frame and each Frame becomes an independent group:
now the user can pick one shipping speed and one payment method without the two interfering.
(Alternatively, set each button's .GroupName property to a shared string; the Frame is the visual and
usually the clearer choice.)
The judgment call: CheckBox or OptionButton
The choice is about the shape of the answer, and it is not a matter of taste:
- Use
CheckBoxwhen options are independent and any number may be on — features to enable, columns to include, opt-ins. Several can be ticked at once. - Use
OptionButton(in aFrame) when the answer is exactly one of a mutually exclusive set — a mode, a speed, a size.
And the anti-pattern to avoid: never fake a radio group with checkboxes by writing code that unticks
the others when one is ticked. That is re-implementing, badly, what an OptionButton group already does
for free — and it is the kind of hand-rolled state that breaks the moment you add a fourth option. If the
answer is one-of-many, use OptionButtons in a Frame.
How ExcelMaster helps
Two failures on this page are quiet and annoying: an If CheckBox1.Value that crashes with Type
mismatch because TripleState slipped a Null in, and radio buttons that clear each other across
unrelated questions because nobody put them in Frames.
ExcelMaster lets you describe the form
in plain words — "three independent opt-in checkboxes, plus a shipping-speed choice and a payment choice"
— and it lays out the CheckBoxes, groups the OptionButtons in their own Frames so they do not
interfere, and reads each control the right way. You keep the workbook and the code.
Frequently asked questions
How do I read whether a CheckBox is ticked in VBA?
Read its .Value, which is a Boolean: If CheckBox1.Value Then ... runs when the box is ticked. Writing
CheckBox1.Value = True ticks it from code. This works cleanly as long as TripleState is False, which
is the default.
Why does If CheckBox1.Value give a Type mismatch error?
Because TripleState is turned on, and the checkbox is in its third, indeterminate state where .Value is
Null. If Null Then raises run-time error 13, Type mismatch. Either leave TripleState = False so the
value is only ever True or False, or test the three states with IsNull(CheckBox1.Value) before the
If.
Why do my option buttons deselect each other across different groups?
Because OptionButton exclusivity is set by the container. Every option button placed directly on the
UserForm is treated as a single group, so unrelated questions interfere. Put each set of option buttons
inside its own Frame (or give each set a distinct .GroupName) to make them independent groups.
What is the difference between a CheckBox and an OptionButton?
A CheckBox is an independent yes/no toggle — any number can be ticked at once. An OptionButton is one
choice from a mutually exclusive group — selecting one clears the rest. Use checkboxes for independent
options and option buttons (grouped in a Frame) when the user must pick exactly one.
How do I group option buttons in a VBA UserForm?
Put each group of OptionButton controls inside its own Frame control; the Frame defines the group, so
buttons in different frames no longer clear each other. If you cannot use frames, set each group's
.GroupName property to a shared, distinct string. Either way, the goal is to give each exclusive question
its own container.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-25.
Related guides: VBA ListBox · VBA ComboBox · VBA UserForm · VBA MsgBox · VBA If Then Else
