VBA 类 未从动态创建的表单对象集合中执行
VBA Classes not executing from collection of dynamically created form objects
我知道这是一个以前被问过的问题,我尝试了多种建议的解决方案,但要么我不太了解大多数解决方案的工作原理,要么发生了其他事情。
该代码从动态创建的表单对象构建一个集合,以发送到 class,在那里它们附加到要执行的事件或至少这就是计划。但是它不想为每个对象执行事件代码,除非在编辑代码后逐步执行它,然后它只会执行一次。
我确实有代码的工作版本,但我想针对运行时对其进行优化,即使它正确生成了表单和对象并将对象添加到集合中的方式与旧代码相同,但它停止工作了.
然后我重写了代码,只是为了看看问题出在哪里,但我似乎无法弄清楚。
这里是简化代码
Dim cEvents As Collection: Set cEvents = New Collection
Dim CntrlH As caCntrlHndlr
Dim OptBtn1 As MSForms.OptionButton
Dim OptBtn2 As MSForms.OptionButton
Dim ChkBx As MSForms.CheckBox
Dim Nm As String
Dim iMvT, iMvL, iOpt As Integer
iOpt = 16
iMvT = 12
i = 0
For Each vKey In .Keys
Set CntrlH = New caCntrlHndlr
Set ChkBx = S5ca1.Frame1.Controls.Add("Forms.CheckBox.1", "Slct" & i, True)
With ChkBx
.Caption = vKey
.Height = iOpt
.Width = Len(CStr(vKey)) * 20
.Left = 6
.Top = iMvT
End With
Set CntrlH.ChkBx = ChkBx
Nm = "X"
iMvL = 5
Set OptBtn1 = S5ca1.Frame2.Controls.Add("Forms.OptionButton.1", Nm & i, True)
With OptBtn1
.GroupName = Nm & i
.Caption = ""
.Height = iOpt
.Width = iOpt
.Left = 5
.Top = iMvT
End With
Set CntrlH.OptBtn1 = OptBtn1
Set OptBtn2 = S5ca1.Frame2.Controls.Add("Forms.OptionButton.1", Nm & i, True)
iMvL = 30
With OptBtn2
.GroupName = Nm & i
.Caption = ""
.Height = iOpt
.Width = iOpt
.Left = 30
.Top = iMvT
End With
Set CntrlH.OptBtn2 = OptBtn2
iMvT = iMvT + 20
i = i + 1
cEvents.Add CntrlH
Next vKey
S5ca1.Height = iMvT + 120
S5ca1.Frame1.Height = iMvT + 10
S5ca1.Frame2.Height = iMvT + 10
S5ca1.OK.Top = S5ca1.Height - 54
End With
End Sub
上面的代码只是其中的一部分所以不要担心最底部的结尾不是问题。
Class代码
Public WithEvents ChkBx As MSForms.CheckBox
Public WithEvents OptBtn1 As MSForms.OptionButton
Public WithEvents OptBtn2 As MSForms.OptionButton
Private Sub ChkBx_Click()
MsgBox "ChkBx"
End Sub
Private Sub OptBtn1_Click()
MsgBox "OptBtn1"
End Sub
Private Sub OptBtn2_Click()
MsgBox "OpBtn2"
End Sub
尝试的解决方案
我知道一个事实,即集合中的每个项目有多个对象可能不是问题所在。我试过对每个项目使用一个对象,但似乎没有用,脚本的工作版本有 Collection 设置。我已经尝试使用 FrmObjct.OnClick="[Event Procedure]"
事件来强制进行交互,除非我以某种方式做错了,否则那是行不通的(我很确定我应用错了)。
考虑到问题的性质,它可能真的很简单,我错过了,但我似乎无法找到那是什么,如果解决方案很简单,我深表歉意。这是我第一次使用 classes.
谢谢你的帮助。
您需要在方法之外保留对 cEvents
集合的引用。否则,您的集合将在方法执行完毕后被销毁。
private cEvents as Collection
Public Sub YourSubFromYourPost()
set cEvents = new Collection
'// the rest of your code here
End Sub
我知道这是一个以前被问过的问题,我尝试了多种建议的解决方案,但要么我不太了解大多数解决方案的工作原理,要么发生了其他事情。
该代码从动态创建的表单对象构建一个集合,以发送到 class,在那里它们附加到要执行的事件或至少这就是计划。但是它不想为每个对象执行事件代码,除非在编辑代码后逐步执行它,然后它只会执行一次。
我确实有代码的工作版本,但我想针对运行时对其进行优化,即使它正确生成了表单和对象并将对象添加到集合中的方式与旧代码相同,但它停止工作了.
然后我重写了代码,只是为了看看问题出在哪里,但我似乎无法弄清楚。
这里是简化代码
Dim cEvents As Collection: Set cEvents = New Collection
Dim CntrlH As caCntrlHndlr
Dim OptBtn1 As MSForms.OptionButton
Dim OptBtn2 As MSForms.OptionButton
Dim ChkBx As MSForms.CheckBox
Dim Nm As String
Dim iMvT, iMvL, iOpt As Integer
iOpt = 16
iMvT = 12
i = 0
For Each vKey In .Keys
Set CntrlH = New caCntrlHndlr
Set ChkBx = S5ca1.Frame1.Controls.Add("Forms.CheckBox.1", "Slct" & i, True)
With ChkBx
.Caption = vKey
.Height = iOpt
.Width = Len(CStr(vKey)) * 20
.Left = 6
.Top = iMvT
End With
Set CntrlH.ChkBx = ChkBx
Nm = "X"
iMvL = 5
Set OptBtn1 = S5ca1.Frame2.Controls.Add("Forms.OptionButton.1", Nm & i, True)
With OptBtn1
.GroupName = Nm & i
.Caption = ""
.Height = iOpt
.Width = iOpt
.Left = 5
.Top = iMvT
End With
Set CntrlH.OptBtn1 = OptBtn1
Set OptBtn2 = S5ca1.Frame2.Controls.Add("Forms.OptionButton.1", Nm & i, True)
iMvL = 30
With OptBtn2
.GroupName = Nm & i
.Caption = ""
.Height = iOpt
.Width = iOpt
.Left = 30
.Top = iMvT
End With
Set CntrlH.OptBtn2 = OptBtn2
iMvT = iMvT + 20
i = i + 1
cEvents.Add CntrlH
Next vKey
S5ca1.Height = iMvT + 120
S5ca1.Frame1.Height = iMvT + 10
S5ca1.Frame2.Height = iMvT + 10
S5ca1.OK.Top = S5ca1.Height - 54
End With
End Sub
上面的代码只是其中的一部分所以不要担心最底部的结尾不是问题。
Class代码
Public WithEvents ChkBx As MSForms.CheckBox
Public WithEvents OptBtn1 As MSForms.OptionButton
Public WithEvents OptBtn2 As MSForms.OptionButton
Private Sub ChkBx_Click()
MsgBox "ChkBx"
End Sub
Private Sub OptBtn1_Click()
MsgBox "OptBtn1"
End Sub
Private Sub OptBtn2_Click()
MsgBox "OpBtn2"
End Sub
尝试的解决方案
我知道一个事实,即集合中的每个项目有多个对象可能不是问题所在。我试过对每个项目使用一个对象,但似乎没有用,脚本的工作版本有 Collection 设置。我已经尝试使用 FrmObjct.OnClick="[Event Procedure]"
事件来强制进行交互,除非我以某种方式做错了,否则那是行不通的(我很确定我应用错了)。
考虑到问题的性质,它可能真的很简单,我错过了,但我似乎无法找到那是什么,如果解决方案很简单,我深表歉意。这是我第一次使用 classes.
谢谢你的帮助。
您需要在方法之外保留对 cEvents
集合的引用。否则,您的集合将在方法执行完毕后被销毁。
private cEvents as Collection
Public Sub YourSubFromYourPost()
set cEvents = new Collection
'// the rest of your code here
End Sub