Land Of Oorang

Or "Things Only I Will Think Are Important"

Blog

Using Excel Checkboxes as Option Groups

Posted by Oorang on November 7, 2009 at 3:10 PM Comments comments (0)

Every now and again I will run across a post like this:

I have created (a) form with check boxes. I am trying program the form so that when a particular box is checked the user cannot check another box in that row. For example, the user should not be able to check "yes", "no" and/or "don't know" at the same time. This is the code I an using, but I keep recieving error messages. What is the problem?

Often such posts are followed by solutions that involve catching the click event of every single CheckBox control, then manually checking each CheckBox that shouldn't be selected and flipping the value: 


Private Sub CheckBox1_Click()
If Me.CheckBox1.Value Then
If Me.CheckBox2.Value Then Me.CheckBox2.Value = False
If Me.CheckBox3.Value Then Me.CheckBox3.Value = False
End If
End Sub

Private Sub CheckBox2_Click()
If Me.CheckBox2.Value Then
If Me.CheckBox1.Value Then Me.CheckBox1.Value = False
If Me.CheckBox3.Value Then Me.CheckBox3.Value = False
End If
End Sub

Private Sub CheckBox3_Click()
If Me.CheckBox3.Value Then
If Me.CheckBox1.Value Then Me.CheckBox1.Value = False
If Me.CheckBox2.Value Then Me.CheckBox2.Value = False
End If
End Sub

    If this code made you cringe, you are not alone. As you can imagine, when you (or the poor soul following you) has to add/rename/delete a CheckBox in future this is going to be real maintenance nightmare. Especially if you, like the user above have a lot of controls. Fortunately there is an easy solution to this problem.

 

    The easiest solution is, of course, to just use Option Groups. No code needed. But some people just really hate radio buttons and want the look of a CheckBox. And since some of those people might be employing you, I will direct your attention to the GroupName property of the CheckBox control. At first glance you might think all your problems are solved. It looks just like the OptionButton.GroupName property! Yay! Sadly, for whatever reason, in VBA this property will hold a value, but the mutual exclusion of an Option Button Group is just not implemented automatically. But don't despair! It's still pretty easy to work around this. With a Class Based approach you can reduce the code in your Form to this:


Private m_cogGroup1 As New CheckOptionGroup
Private m_cogGroup2 As New CheckOptionGroup

Private Sub UserForm_Initialize()
m_cogGroup1.InitializeGroup "Group1", Me.Controls
m_cogGroup2.InitializeGroup "Group2", Me.Controls
End Sub

 

To do this:

  1. Import the two classes posted below.
  2. Go ahead and use the GroupName property to specify your groups of checkboxes (just like you would an option group).
  3. Implement as shown above, using one array of CheckOptionGroup for each group.

To make life a little easier, I have created an Example Workbook.

 

If you just want to copy/paste the code use these:

CheckOption.cls

CheckOptionGroup.cls

 

These are also stored in the Code Archive.

Friday 5/29/2009 - NateOwned

Posted by Oorang on June 5, 2009 at 5:42 AM Comments comments (0)

If you hang out on MrExcel then you know why this is funny (click for a larger view):




You can visit Nate Oliver's blog here: http://msmvps.com/blogs/nateoliver/

Friday 8/22/2008 - Excel InStrRev

Posted by Oorang on June 5, 2009 at 5:24 AM Comments comments (0)

VBA has a really useful function called InStrRev that finds the last occurrence of a sub-string in a string. To give an example InStrRev("C:\Test\Bar","\") would return 7 which is the position of the rightmost (or last) backslash. This is a very handy function to have around when you need to perform certain text parsing tasks, such as extracting a file name from a path etc.

Unfortunately, while Excel has FIND and SEARCH functions that work like InStr, there is no Excel equivialent to InStrRev. A lot of people simply use a UDF (user defined fuction) to just call the InStrRev in VBA, but there is a way to do it with just Excel formulas. Here is how:

=FIND(CHAR(26,),SUBSTITUTE("A1","MySubString",CHAR(26),(LEN(A1)-LEN(SUBSTITUTE(A1,"MySubString","")))/LEN("MySubString")))

How It Works:

The FIND and SEARCH functions can only find the first occurance of a substring. So in order to find the last occurance of a substring you must first make that substring unique within the string so it (and only it) will be found. The SUBSTITUTE function will replace a specific occurance of a substring with something unique. But you have to be able to specify the occurance number. We want the last occurance so all we need is a straight count of how many times the specified substring occurs in a string. Now to put it all together:

1.) Assume A1 has the value "C:\Test\Foo"
2.) Find the occurances of the specified substring within the string:
=FIND(CHAR(26,),SUBSTITUTE("A1","\",CHAR(26),LEN(A1)-LEN(SUBSTITUTE(A1,"","")))/LEN("\")))
=FIND(CHAR(26,),SUBSTITUTE("A1","\",CHAR(26),(11-9)/1))
=FIND(CHAR(26,),SUBSTITUTE("A1","\",CHAR(26),2))
4.) Replace the last occurance of the substring with a special char unlikely to occur in a string (I used the substitute character, it seemed fitting):
=FIND(" ","C:\Test Foo")
= 8