Reputation: 33
I have a button that generates ActiveX checkboxes based on a range of cells that the user selects. These checkboxes are linked to their corresponding cell. Additionally, a master checkbox is generated along with them that is intended to check/uncheck the rest of the checkboxes.
What I am trying to do is have an event occur when this master checkbox is checked and ends up checking the rest.
I was thinking of something like this which is the creation of my Master Checkbox:
Sub AddMasterCheckbox(cbNum As Integer, cbIdent As String, Rng As Range)
Dim name
With ActiveSheet.OLEObjects.Add(ClassType:="Forms.CheckBox.1", _
Left:=1033.5, Top:=Rng.Top, Width:=150.5, Height:=20.75)
If cbNum < 10 Then
.name = "NewCheckBox" & cbIdent & "0" & cbNum
Else
.name = "NewCheckBox" & cbIdent & cbNum
End If
name = .name
.Object.Caption = "Select all for this Machine"
.Object.OnAction = "'SelectAll ""name""'"
End With
End Sub
However, I am getting an error, stating that this is not supported. Essentially, I have another subprogram called SelectAll which ideally would be called when the master checkbox is clicked.
How can I go about to doing this?
Upvotes: 1
Views: 1617
Reputation: 22195
The easiest solution is to simply use Form Controls instead of ActiveX controls. That said...
The result of ActiveSheet.OLEObjects.Add
is going to be an OLEObject
that contains a MSForms.CheckBox
as its .Object
. It doesn't have an OnAction
member.
It does, however, source automation events (it would be pretty worthless on a form without them). That means you can grab a reference, store it, and handle its events:
'This code can't be in a module.
Private WithEvents master As MSForms.CheckBox
Sub AddMasterCheckbox(cbNum As Integer, cbIdent As String, Rng As Range)
Set master = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CheckBox.1", _
Left:=1033.5, Top:=Rng.Top, Width:=150.5, Height:=20.75).Object
With master
If cbNum < 10 Then
.Name = "NewCheckBox" & cbIdent & "0" & cbNum
Else
.Name = "NewCheckBox" & cbIdent & cbNum
End If
Name = .Name
.Object.Caption = "Select all for this Machine"
End With
End Sub
Private Sub master_Change()
SelectAll master.Name
End Sub
Note that the life-time of the event handler will be the life-time of whatever class you store master
in. If you need to "re-wire" it after the workbook is closed, you'll need to do that in Workbook_Open
or some other handler that will fire before the checkboxes are accessible. If that's the case, it might be better to create a simple wrapper class:
'In a class module named CheckboxWrapper.
Private WithEvents m_wrapped As MSForms.CheckBox
Public Property Get WrappedCheckBox() As MSForms.CheckBox
Set WrappedCheckBox = m_wrapped
End Property
Public Sub GenerateCheckbox(cbNum As Integer, cbIdent As String, Rng As Range)
Set m_wrapped = Rng.Parent.OLEObjects.Add(ClassType:="Forms.CheckBox.1", _
Left:=1033.5, Top:=Rng.Top, Width:=150.5, Height:=20.75).Object
With m_wrapped
If cbNum < 10 Then
.Name = "NewCheckBox" & cbIdent & "0" & cbNum
Else
.Name = "NewCheckBox" & cbIdent & cbNum
End If
.Object.Caption = "Select all for this Machine"
End With
End Sub
Private Sub m_wrapped_Change()
SelectAll master.Name
End Sub
You'd use it something like this:
Private checkboxes As Collection
Private Sub Workbook_Open()
Dim ole As OLEObject
For Each ole In Sheet1.OLEObjects 'Or whatever sheet they're on
If TypeName(cbx) = "CheckBox" Then
Dim cbx As CheckboxWrapper
Set cbx = New CheckboxWrapper
Set cbx.WrappedCheckBox = ole.Object
checkboxes.Add cbx
End If
Next
End Sub
Upvotes: 0
Reputation:
ActiveX controls do not have an .OnAction
method. FYI: Forms.CheckBox.1
refers to an MS Forms Checkbox not an Excel Forms Control.
Sub AddMasterCheckbox(cbNum As Integer, cbIdent As String, Rng As Range)
Dim name
With ActiveSheet.CheckBoxes.Add(Left:=1033.5, Top:=Rng.Top, Width:=150.5, Height:=20.75)
If cbNum < 10 Then
.name = "NewCheckBox" & cbIdent & "0" & cbNum
Else
.name = "NewCheckBox" & cbIdent & cbNum
End If
name = .name
.Caption = "Select all for this Machine"
.OnAction = "'SelectAll ""name""'"
End With
End Sub
Note: If you prefer to use ActiveX controls you could use a User Defined Class to group the COntrols events. See my answer to Returning an index value from a group of ActiveX Option Buttons
Upvotes: 1