Excel 在userform模块中以编程方式创建命令按钮和编写代码
这就是我想做的: 1检查文件夹中文件的版本数 2在用户窗体中添加与版本数相同的按钮 3为每个按钮编写代码,例如,显示MsgBox 使用下面的代码,可以正确地检查版本数,也可以正确地创建按钮,并且代码可以正确地添加到userform模块中,但是。。。当我点击任何按钮(为每个版本创建)时,什么都没有发生。救命啊Excel 在userform模块中以编程方式创建命令按钮和编写代码,excel,vba,Excel,Vba,这就是我想做的: 1检查文件夹中文件的版本数 2在用户窗体中添加与版本数相同的按钮 3为每个按钮编写代码,例如,显示MsgBox 使用下面的代码,可以正确地检查版本数,也可以正确地创建按钮,并且代码可以正确地添加到userform模块中,但是。。。当我点击任何按钮(为每个版本创建)时,什么都没有发生。救命啊 Dim Boton As MSForms.CommandButton Dim Fichero_Secundaria_Hoy As String Dim Versiones_secundari
Dim Boton As MSForms.CommandButton
Dim Fichero_Secundaria_Hoy As String
Dim Versiones_secundaria(8) As Integer
Dim i As Integer
Dim Number_of_versions As Integer
Dim Code As String
Dim j As Integer
Fichero_Secundaria_Hoy = Dir("C:\Prueba\pdvd_" & Format(Date, "yyyymmdd") & "*")
Do While Fichero_Secundaria_Hoy <> ""
Versiones_secundaria(i) = Mid(Fichero_Secundaria_Hoy, 27, 1)
Fichero_Secundaria_Hoy = Dir
i = i + 1
Loop
Number_of_versions = i
Version_secundaria.Height = 18 + 24 * Number_of_versions
With ActiveWorkbook.VBProject.VBComponents("Version_secundaria").CodeModule
.DeleteLines 1, .CountOfLines
End With
For i = 0 To Number_of_versions - 1
Set Boton = Version_secundaria.Controls.Add("Forms.commandbutton.1", "Version" & Versiones_secundaria(i))
Version_secundaria.Controls("version" & Versiones_secundaria(i)).Caption = Versiones_secundaria(i)
Code = "Sub " & Boton.Name & "_Click()" & vbCrLf
Code = Code & "Call Mostrar_secundaria" & vbCrLf
Code = Code & "Version_secundaria.Hide" & vbCrLf
Code = Code & "End Sub"
With ActiveWorkbook.VBProject.VBComponents("Version_secundaria").CodeModule
.InsertLines .CountOfLines + 1, Codigo_del_boton
End With
Next i
Dim Boton As MSForms.CommandButton
Dim Fichero_Secundaria_Hoy作为字符串
Dim Versiones_secundaria(8)作为整数
作为整数的Dim i
作为整数的\u版本的Dim编号\u
将代码设置为字符串
作为整数的Dim j
Fichero_Secundaria_Hoy=Dir(“C:\Prueba\pdvd_wd”和格式(日期,yyyymmdd)和“*”)
当菲切罗(Fichero_Secundaria_Hoy)的时候
第二版(i)=中期(第27、1页)
Fichero_Secundaria_Hoy=Dir
i=i+1
环
版本的数量=i
版本号?secundaria.Height=18+24*版本号
使用ActiveWorkbook.VBProject.VBComponents(“Version_secundaria”).CodeModule
.DeleteLines 1、.countofline
以
对于i=0到版本数-1
Set Boton=Version\u secundaria.Controls.Add(“Forms.commandbutton.1”、“Version”和Versiones\u secundaria(i))
Version_secundaria.Controls(“Version”和Versiones_secundaria(i))。Caption=Versiones_secundaria(i)
Code=“Sub”&Boton.Name&“\u Click()”&vbCrLf
代码=代码和“呼叫Mostrar\u secundaria”和vbCrLf
Code=Code&“Version\u secundaria.Hide”&vbCrLf
代码=代码和“末端接头”
使用ActiveWorkbook.VBProject.VBComponents(“Version_secundaria”).CodeModule
.InsertLines.CountOfLines+1,Codigo_del_boton
以
接下来我
此代码位于普通模块中,以编程方式编写的代码出现在名为“Version_secundaria”的现有用户表单模块中
似乎点击按钮并不意味着点击子按钮,但不知道为什么
谢谢大家! 我不相信你想要的是可能的。一两年前也有类似的问题。OP的目标与您的目标非常不同,但也需要在运行时创建源代码。我记得OP被告知不可能在同一次运行中创建和执行源代码。我在网上找不到任何东西来证实或否认这一限制。我还记得,发布了一个替代方法来满足该要求。可能是我,因为我记得我在考虑如何达到所需的效果
你也可以考虑C皮尔森的警告:
警告:许多基于VBA的计算机病毒通过 创建和/或修改VBA代码。因此,许多病毒扫描程序可能 在没有警告或确认的情况下自动删除 引用VBProject对象,导致永久性和不可恢复的错误 代码丢失。请参阅您的防病毒软件的文档 详情请参阅 下面的代码提供了另一种方法来实现我相信您所寻求的效果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
我创建了一个用户表单,并用20个选项按钮、1个命令按钮和1个标签填充它。我将表单和控件保留为默认名称,但将命令按钮重命名为cmdExit。我把退出按钮和标签放在我想要的地方。选项按钮随机放置,并使其不可见(属性Visible=False)。这可能不足以满足您的需要,但在窗体明显变慢之前,您可以拥有很多很多控件
我创建了一个小例程来显示表单:
Option Explicit
Sub DsplForm()
Load UserForm1
UserForm1.Show vbModal
End Sub
表单中代码的基础是集合控件
,其中包含表单上的所有控件。您可以通过控件名称或控件集合访问控件的属性。例如,如果控件5为Label1,则以下内容等效:
Label1.Caption = "xxxx"
Controls(5).Caption = "xxxx"
这允许运行时访问类似控件,而无需为每个控件指定特定代码
我使用表单的初始化例程来准备一切:
控件
,并对其进行计数控件中的OptionButton1
之前,很难获取OptionButton2
,但如果您这样做了,这并不重要
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
选项显式
Dim OptButCtrl()尽可能长
Dim OptButDesc()作为字符串
私有子cmdExit_Click()
卸下我
端接头
'VB.Net具有允许一个例程处理事件的功能
“几个控件。我找不到与VBA等价的函数性。这
“这是我找到的最好的方法。
专用子选项按钮1\u单击()
呼叫选项按钮(1)
端接头
专用子选项按钮2\u单击()
呼叫选项按钮(2)
端接头
专用子选项按钮3_单击()
呼叫选项按钮(3)
端接头
专用子选项按钮4_单击()
呼叫选项按钮(4)
端接头
专用子选项按钮5_单击()
呼叫选项按钮(5)
端接头
专用子选项按钮6_单击()
呼叫选项按钮(6)
端接头
私人次级选择权