PDA

View Full Version : Generic Statement for Linking CheckBoxes



Ulic
04-15-2009, 05:07 PM
I've created a huge checklist in Word 2007 using the checkbox feature. Some of these checkboxes exist in a hierarchy, for example, say I have a one item shopping list with a checkbox named "Groceries" and one item under that named "Bananas". If "Bananas" is checked the checkbox above it, "Groceries" should also be checked.
I have written a few simple If statement so when a box is clicked it will check or uncheck another box. The second statement is slightly more complex marking as true and locking the checkbox above it in the hierarchy. For the example above CheckBox1 would equate to "Groceries" and CheckBox1a would equate to "Bananas"

Private Sub CheckBox1_Click()
If CheckBox1.Value = True Then
CheckBox1a.Value = True
End If
End Sub
Private Sub CheckBox1a_Click()
If CheckBox1a.Value = True Then
CheckBox1.Value = True
CheckBox1.Locked = True
Else
CheckBox1.Value = False
CheckBox1.Locked = False
End If
End Sub Now I'm literally rewriting this code over and over again for each and every one of these little checkbox hierarchies I have. Each time I'm only changing the checkbox that I'm referencing (CheckBox2 and Checkbox2a instead of CheckBox1 and Checkbox1a) Can't I just write one If statement referencing a generic CheckBox and use the Call function under these Subs to run it? My question is how do I do that? I've tried a few things but keep running into errors. Something along these lines?

Dim X As Variable
Dim Y As Variable
Private Sub CheckBoxX()
X = 1
Y = 1a
If CheckBox(X).Value = True Then
CheckBox(Y).Value = True
End If
End Sub
Private Sub CheckBoxY()
X = 1
Y = 1a
If CheckBox(Y).Value = True Then
CheckBox(X).Value = True
CheckBox(X).Locked = True
Else
CheckBox(X).Value = False
CheckBox(X).Locked = False
End If
End Sub That doesn't work obviously because I have no idea what I'm doing but I hope you get the gist of what I'm trying to do. Thanks in advance for any help.

fumei
04-17-2009, 01:17 PM
1. What fires Sub CheckBoxY()????

2. Start getting into the habit of always giving explicit names to objects. Which leads to....

3. "Can't I just write one If statement referencing a generic CheckBox " Ummm, no.

There is no such thing as a "generic" Checkbox. Fortunately VBA works by referencing specific things.

I am not quite following your logic.

"For the example above CheckBox1 would equate to "Groceries" and CheckBox1a would equate to "Bananas"

And the code....
Private Sub CheckBox1_Click()
If CheckBox1.Value = True Then
CheckBox1a.Value = True
End If
End Sub
In which case, if "Groceries" is EVER True, then "Bananas" is ALWAYS True.

Surely that can not be the case. "Bananas" are always True, if ever Groceries is True? If that is correct...why have "Bananas" at all? You could have it that if Groceries is True, Bananas (within later logic) is included.

However, in any case, unless you possibly rethink the logic design (which may be a good idea), then no, you are stuck with working with explicit logic for each checkbox.

Ulic
04-17-2009, 03:14 PM
Thanks for the response. As you can probably tell I just started messing around with VBA last weekend but its really straight forward and easy enough to learn. I figured out how to do what I wanted but I'll take your points as you listed them. Skip to the end to see what I can up with and was really asking for.
1. In the example I was using the CheckBoxX() and CheckBoxY() code I wrote would have been fired on click for CheckBox1 and CheckBox1a example.

Private Sub CheckBox1_Click()
Call CheckBoxX
End Sub
Private Sub CheckBox1a_Click()
Call CheckBoxY
End Sub Again this was all in an effort to avoid having to write basically the same code over and over for each checkbox. Now I know what I wrote doesn't work I was hoping it would help illustrate what I was asking for in case It wasn't clear from my description.
2. I understand the benefit of giving explicit names to objects, again in the example above I wrote it that way because I was hoping that it would be possible to give generic numbered names to the checkboxes and write a sub that I could call for all of the CheckBoxes I have.
3. I understand that there is not a generic checkbox it just seems silly to write virtually the same code over and over again and that there must be some way around it. I was hoping someone would say "sure you can do that with an array, here’s how", (it turns out it wasn't that complicated at all).
And again let me try and explain my example by expanding it to something closer to what I'm actually doing. And yes it's true that I intentionally set it us so that if the main heading of Groceries is EVER True Bananas is ALWAYS True. Perhaps I refined it down to much to be useful as an example.

I have a list of things in a word document set up as a checklist using checkboxes. As an example let's say it's a to do list containing a shopping list with a main heading of Groceries, with items below that. It is set up as such:

[ ] Grocheries
[ ] Bananas
[ ] Apples I wrote subs that fire on click that will check some of the boxes for me. Let's say for example I bought all my groceries but didn't check off all my items one at a time. I want to be able to click Groceries and have all the items under that heading marked as true. See code:

Private Sub Groceries_Click()
If Groceries.Value = True Then
Bananas.Value = True
Apples.Value = True
End If
End Sub Now I don't have it set up to uncheck all the boxes if Groceries is marked as False out of personal preference. (If I marked it by accident and purchased some of the items I'm going to have to go back through the list and check things off manually anyway so what's the point of having them all unchecked?)
But if I am checking each item off one at a time as I grab them I have subs that fire on click for each of the items under then main heading to check if everything has been marked as True under that main heading and if that is the case mark the main heading as true.

Private Sub Grocery_Items()
If Bananas.Value = True Then
If Apples.Value = True Then
Groceries.Value = True
Groceries.Locked = True
Else
Groceries.Value = False
Groceries.Locked = False
End If
Else
Groceries.Value = False
Groceries.Locked = False
End If
End Sub

Private Sub Bananas_Click()
Call Grocery_Items
End Sub

Private Sub Apples_Click()
Call Grocery_Items
End Sub Lets say I have another packing list for Toiletries so I don’t forget them. This list includes Toothbrush and Toothpaste. You can see that its going to look almost exactly the same as my above example but the names will be different. Now I can write the code again for each checkboxes on click just changing the name but it would be much and more elegant if I had a generic sub I could call.
Here is what I ultimately came up with:

Private Sub CheckBox()
Dim X As Object
Dim Y As Object
Dim Z As Object
If X.Value = True Then
Y.Value = True
Z.Value = True
End If
End Sub

Private Sub CheckBoxa()
Dim X As Object
Dim Y As Object
Dim Z As Object
If Y.Value = True Then
If Z.Value = True Then
X.Value = True
X.Locked = True
Else
X.Value = False
X.Locked = False
End If
Else
X.Value = False
X.Locked = False
End If
End Sub

Private Sub Groceries_Click()
X = Groceries
Y = Bananas
Z = Apples
Call CheckBox
End Sub

Private Sub Bananas_Click()
X = Groceries
Y = Bananas
Z = Apples
Call CheckBoxa
End Sub

Private Sub Apples_Click()
X = Groceries
Y = Bananas
Z = Apples
Call CheckBoxa
End Sub I declear the varables in each sub rather than in the "Generic" one because they won't always equal those specific checkboxes. As you can see my problem was that I was trying to jam an object into the checkbox when I really just needed to create a placeholder for the checkbox as a whole. Odd that I didn't see that to begin with, it took me two days.
Now I get the impression from you're post that you may be a little exasperated with me and my layman's understanding of VBA but I'm more than willing to listen to and accept and suggestions you may have for improving what I've come up with if you're willing to offer them. Anyway thanks again for your input.

Paul_Hossler
04-20-2009, 09:17 AM
Maybe not the cleanest way to do it, but may give you some ideas.

I have 2 upper level check boxes named Groceries and Drinks, and they have some second levels, also named


Option Explicit
Private Sub Bread_Click()
Groceries.Value = ProcessAllClicks(Bread)
End Sub
Private Sub Cheese_Click()
Groceries.Value = ProcessAllClicks(Cheese)
End Sub
Private Sub Milk_Click()
Drinks.Value = ProcessAllClicks(Milk)
End Sub
Private Sub Water_Click()
Drinks.Value = ProcessAllClicks(Water)
End Sub
Private Sub Beer_Click()
Drinks.Value = ProcessAllClicks(Beer)
End Sub


Private Function ProcessAllClicks(o As Object) As Boolean
Select Case LCase(o.Caption)
Case "bread", "cheese"
ProcessAllClicks = Bread Or Cheese

Case "milk", "water", "beer"
ProcessAllClicks = Milk Or Water Or Beer
End Select

End Function



Paul

fumei
04-20-2009, 10:01 AM
Paul, just for convenience sake, could you please post non-2007 files? .docm is version 2007 format, and I can not look at it, which I would like to. I mean I can...sort of..but, for example, all ActiveX controls (like your checkboxes) are disabled. Therefore, all your _Click code procedures do not fire (even from the VBE).

Paul_Hossler
04-20-2009, 03:36 PM
Point taken, however the OP did say specifically say ...



I've created a huge checklist in Word 2007 using the checkbox feature.

so I didn't think a 2003 file format would be of much use to him, since as you say, the ActiveX model works differently


Paul

:friends: ??

fumei
04-22-2009, 10:37 AM
Doh...stupid me. Yes, of course. Sorry.