如何为VBA用户窗体中动态创建的TextBox创建_Change()事件?
问题根源与修正方案
你的代码核心问题有两个:
- 类实例的作用域错误:
conditionCommand是过程级局部变量,addConditions执行完毕后会被VBA自动销毁,导致后续TextBox的Change事件失去关联对象 - 对象赋值方式错误:TextBox是对象类型,类模块中用
Property Let赋值会失效,必须用Property Set
步骤1:修正类模块conditionEventClass
将原来的Property Let改为Property Set(对象类型赋值必须用Set):
Public WithEvents conditionEvent As MSForms.TextBox Public Property Set textBox(boxValue As MSForms.TextBox) Set conditionEvent = boxValue End Property Public Sub conditionEvent_Change() MsgBox conditionEvent.Name & " changed." End Sub
步骤2:修正标准模块代码
在模块级别声明集合来保存类实例,确保实例不会被销毁;同时优化控件命名避免重复:
' 模块级别声明,持久保存所有动态TextBox对应的类实例 Private conditionCommandCollection As Collection Sub addConditions() Dim conditionCommand As conditionEventClass Dim newTextBox As MSForms.TextBox ' 初始化集合(仅第一次调用时执行) If conditionCommandCollection Is Nothing Then Set conditionCommandCollection = New Collection End If ' 创建动态TextBox Set newTextBox = commandRequestForm.MultiPage1(1).Controls.Add("Forms.TextBox.1", , True) With newTextBox .Name = "conditionValue" & conditionCommandCollection.Count + 1 ' 避免同名控件 .Left = 750 .Height = 15 .Width = 100 .Top = 20 + (conditionCommandCollection.Count * 20) ' 控件依次向下排列 End With ' 关联类实例与TextBox Set conditionCommand = New conditionEventClass Set conditionCommand.textBox = newTextBox ' 将类实例存入集合,保持引用不被销毁 conditionCommandCollection.Add conditionCommand End Sub
关键说明
- 模块级集合
conditionCommandCollection:只要模块处于加载状态,集合就会保留所有类实例,确保TextBox的Change事件始终能触发类中的处理过程 - 控件命名加序号:避免多次调用
addConditions时创建同名控件,导致运行时错误 - 调整控件Top位置:让动态创建的TextBox不重叠,方便测试触发事件
内容的提问来源于stack exchange,提问作者Nik Ohler
相关产品推荐
相关产品推荐

