我不相信你想要的东西是可能的。一两年前有一个类似的问题。 OP 的目标与您的非常不同,但也需要在运行时创建源代码。我的回忆是,OP 被告知不可能在同一运行中创建和执行源代码。我在网上找不到任何东西来确认或否认这一限制。我还记得发布了该要求的另一种方法。可能是我,因为我记得考虑如何达到所需的效果。
您可能还想考虑来自 C Pearson 的警告:
注意:许多基于 VBA 的计算机病毒通过以下方式自行传播
创建和/或修改 VBA 代码。因此,许多病毒扫描程序可能
自动且没有警告或确认删除模块
引用 VBProject 对象,导致永久且无法恢复
代码丢失。请查阅您的防病毒软件的文档
了解详情。
下面的代码提供了一种替代方法来实现我相信您寻求的效果。
我创建了一个用户表单,并在其中填充了 20 个选项按钮、1 个命令按钮和 1 个标签。除了重命名为 cmdExit 的命令按钮外,我已将表单和控件保留为默认名称。我将退出按钮和标签放在我希望它们出现的位置。选项按钮被随机放置并且不可见(属性可见 = False)。这可能不足以满足您的需求,但您可以在表单明显变慢之前拥有更多的控件。
我创建了一个小程序来显示表单:
Option Explicit
Sub DsplForm()
Load UserForm1
UserForm1.Show vbModal
End Sub
表单中代码的基础是集合Controls,其中包含表单上的所有控件。您可以通过控件名称或控件集合访问控件的属性。例如,如果控件 5 是 Label1,则以下是等价的:
Label1.Caption = "xxxx"
Controls(5).Caption = "xxxx"
这允许运行时访问类似的控件,而无需为每个控件指定特定代码。
我使用表单的初始化例程来准备一切:
- 扫描
Controls 查找选项按钮并计数。
- 根据按钮的数量调整数组 OptButCtrl 的大小。
- 记录数组 OptButCtrl 中每个按钮的控件编号。我不关心顺序。在
Controls 中很难在OptionButton1 之前获得OptionButton2,但如果你这样做也没关系。
- 我初始化数组 OptButDesc()。这是确定显示多少选项按钮的数组。您需要根据版本数调整此数组的大小,并使用版本的名称和详细信息加载此数组。
- 适当数量的选项按钮显示在列表中。
所有选项按钮的单击例程调用一个例程,该例程将所有选项按钮设置为关闭/假,而不是选定的按钮。 Label1 设置为所选按钮的描述。
如有必要,请提出问题,但我相信我已经为您提供了足够的信息来展示如何实现您所寻求的效果。
Option Explicit
Dim OptButCtrl() As Long
Dim OptButDesc() As String
Private Sub cmdExit_Click()
Unload Me
End Sub
' VB.Net has the functionality to allow one routine handle the events for
' several controls. I can find no equivalent functonality with VBA. This
' approach is the best I have found.
Private Sub OptionButton1_Click()
Call OptionButtonAny(1)
End Sub
Private Sub OptionButton2_Click()
Call OptionButtonAny(2)
End Sub
Private Sub OptionButton3_Click()
Call OptionButtonAny(3)
End Sub
Private Sub OptionButton4_Click()
Call OptionButtonAny(4)
End Sub
Private Sub OptionButton5_Click()
Call OptionButtonAny(5)
End Sub
Private Sub OptionButton6_Click()
Call OptionButtonAny(6)
End Sub
Private Sub OptionButton7_Click()
Call OptionButtonAny(7)
End Sub
Private Sub OptionButton8_Click()
Call OptionButtonAny(8)
End Sub
Private Sub OptionButton9_Click()
Call OptionButtonAny(9)
End Sub
Private Sub OptionButton10_Click()
Call OptionButtonAny(10)
End Sub
Private Sub OptionButton11_Click()
Call OptionButtonAny(11)
End Sub
Private Sub OptionButton12_Click()
Call OptionButtonAny(12)
End Sub
Private Sub OptionButton13_Click()
Call OptionButtonAny(13)
End Sub
Private Sub OptionButton14_Click()
Call OptionButtonAny(14)
End Sub
Private Sub OptionButton15_Click()
Call OptionButtonAny(15)
End Sub
Private Sub OptionButton16_Click()
Call OptionButtonAny(16)
End Sub
Private Sub OptionButton17_Click()
Call OptionButtonAny(17)
End Sub
Private Sub OptionButton18_Click()
Call OptionButtonAny(18)
End Sub
Private Sub OptionButton19_Click()
Call OptionButtonAny(19)
End Sub
Private Sub OptionButton20_Click()
Call OptionButtonAny(20)
End Sub
Private Sub UserForm_Initialize()
Dim InxCtrl As Long
Dim InxOptBut As Long
Dim Left As Long
Dim NumOptButs As Long
Dim Top As Long
' Scan all controls and count those that are Option buttons
NumOptButs = 0
For InxCtrl = 0 To Controls.Count - 1
With Controls(InxCtrl)
If Mid(.Name, 1, 12) = "OptionButton" Then
NumOptButs = NumOptButs + 1
End If
End With
Next
' Size array according to number of option buttons found
ReDim OptButCtrl(0 To NumOptButs - 1)
' Record control numbers of option buttons in array OptButCtrl()
InxOptBut = LBound(OptButCtrl)
For InxCtrl = 0 To Controls.Count - 1
With Controls(InxCtrl)
If Mid(.Name, 1, 12) = "OptionButton" Then
OptButCtrl(InxOptBut) = InxCtrl
InxOptBut = InxOptBut + 1
End If
End With
Next
' The lower bound of OptButCtrl and OptButDesc must be the same.
' The size of this array controls how many option buttons are displayed.
ReDim OptButDesc(0 To 5)
OptButDesc(0) = "Desc for Button 1"
OptButDesc(1) = "Desc for Button 2"
OptButDesc(2) = "Desc for Button 3"
OptButDesc(3) = "Desc for Button 4"
OptButDesc(4) = "Desc for Button 5"
OptButDesc(5) = "Desc for Button 6"
' These control the top left corner of the first option button
Left = 5
Top = 5
' Display one button for each description in OptButDesc()
For InxOptBut = LBound(OptButCtrl) To UBound(OptButCtrl)
InxCtrl = OptButCtrl(InxOptBut)
If InxOptBut <= UBound(OptButDesc) Then
' This button is required
With Controls(InxCtrl)
.Top = Top
Top = Top + .Height + 5
.Left = Left
.Visible = True
.Caption = OptButDesc(InxOptBut)
End With
Else
' This button is not required
Controls(InxCtrl).Visible = False
End If
Next
End Sub
Sub OptionButtonAny(ByVal OptButNum As Long)
Dim InxCtrl As Long
Dim InxOptBut As Long
' Find Control for selected Option button.
' Set all other option buttons to Off.
' Display description of selected button in Label1
For InxOptBut = LBound(OptButCtrl) To UBound(OptButCtrl)
InxCtrl = OptButCtrl(InxOptBut)
With Controls(InxCtrl)
If .Name = "OptionButton" & OptButNum Then
Label1.Caption = OptButDesc(InxOptBut)
Else
.Value = False
End If
End With
Next
End Sub
我应该补充一点,我不相信这是处理您的要求的最佳方式。我相信我会将所有版本加载到 ListBox 并让用户选择所需的行。