最简单的解决方案是简单地使用表单控件而不是 ActiveX 控件。那就是……
ActiveSheet.OLEObjects.Add 的结果将是一个OLEObject,其中包含一个MSForms.CheckBox 作为它的.Object。它没有OnAction 成员。
但是,它确实提供了源自动化事件(如果没有它们,它在表单上将毫无价值)。这意味着您可以获取引用、存储它并处理它的事件:
'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
请注意,事件处理程序的生命周期将是您存储 master 的任何类的生命周期。如果您需要在工作簿关闭后“重新连接”它,您需要在Workbook_Open 或在复选框可访问之前触发的其他处理程序中执行此操作。如果是这种情况,创建一个简单的包装类可能会更好:
'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
你会像这样使用它:
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