宏中的用户窗体控制变量

Userform controlled variables within a macro

早安,

我的项目 运行 遇到了一个小障碍。我是 VBA 的新手,正在尽最大努力 'learn by doing' 但我似乎无法理解 macro/userform 互动。

我有一个包含一个文本框和 9 个复选框的用户表单。这应该显示用户表单,允许用户指定 sheet 名称,以及(来自 9 个用户的列表)select 是否处于活动状态(真或假)。

在我的主子中,我只有一个

Allocator.show

command,你可能已经猜到了,allocator是我的用户名。

然后我一直在尝试一些事情,所以我不知道其余的用户表单代码有多正确;

Private Sub cbGo_Click()

Unload Allocator

End Sub

Private Sub cboxAlison_Click()

If Me.cboxAlison.Value = True Then
    AlisonYN = True
        Else
    AlisonYN = False
End If

End Sub

Private Sub cboxBeverly_Click()

If Me.cboxBeverly.Value = True Then
    BevelyYN = True
        Else
    BevelyYN = False
End If

End Sub

Private Sub cboxCallum_Click()

If Me.cboxCallum.Value = True Then
    CallumYN = True
        Else
    CallumYN = False
End If

End Sub

Private Sub cboxEllen_Click()

If Me.cboxEllen.Value = True Then
    EllenYN = True
        Else
    EllenYN = False
End If

End Sub

Private Sub cboxGeoff_Click()

If Me.cboxGeoff.Value = True Then
    GeoffYN = True
        Else
    GeoffYN = False
End If

End Sub

Private Sub cboxJames_Click()

If Me.cboxJames.Value = True Then
    JamesYN = True
        Else
    JamesYN = False
End If

End Sub

Private Sub cboxLouise_Click()

If Me.cboxLouise.Value = True Then
    LouiseYN = True
        Else
    LouiseYN = False
End If

End Sub

Private Sub cboxMick_Click()

If Me.cboxMick.Value = True Then
    MickYN = True
        Else
    MickYN = False
End If

End Sub

Private Sub cboxTammy_Click()

If Me.cboxTammy.Value = True Then
    TammyYN = True
        Else
    TammyYN = False
End If

End Sub

Private Sub tbRPName_Change()

End Sub

Private Sub UserForm_Initialize()

Dim GeoffYN, TammyYN, CallumYN, JamesYN, MickYN, AlisonYN, BeverlyYN, LouiseYN, EllenYN As Boolean
Dim RP_Name As String

Me.cboxGeoff.Value = True


Me.cboxTammy.Value = True


Me.cboxCallum.Value = True


Me.cboxJames.Value = True


Me.cboxMick.Value = False


Me.cboxAlison.Value = False


Me.cboxBeverly.Value = False


Me.cboxLouise.Value = False


Me.cboxEllen.Value = False

Me.tbRPName = ""

End Sub

所有命名的用户变量 (xxxxYN) 在我的主模块中 public。

这些是我想在用户选中所需的框后将变量作为 true 或 false 拉回到我的主宏中,以及作为字符串的名称,然后继续 运行 原始宏。

任何帮助将不胜感激,我现在​​似乎在兜圈子!

PS 如果有帮助,我的用户表单如下所示;

UserForm

干杯,

卡勒姆

我不知道实际问题是什么,但我试图重现你的问题,只是决定向你展示我所拥有的。看看这些是否对您有帮助。

所有这些代码都在用户窗体代码中,而不是在模块级别。当我更改复选框值时,这些值将被存储(在主子之外,在 "check" 子单击事件中验证)。

为了让你的代码更短一些,你可以直接将复选框的值赋给一个变量

Dim test as Boolean
test = me.CheckBox1.Value

您可以将其插入到您的转到按钮的代码中

你写了 "All of the named user variables (xxxxYN) are public in my main module." 但我们也看到它们在用户窗体的 Sub UserForm_Initialize 中声明:

Private Sub UserForm_Initialize()

Dim GeoffYN, TammyYN, CallumYN, JamesYN, MickYN, AlisonYN, BeverlyYN, LouiseYN, EllenYN As Boolean
Dim RP_Name As Stringn
...

即使您在任何模块中声明了与 Public 相同的变量,用户窗体变量也会隐藏它们的 Public namsakes 因此任何用户窗体设置都不是 "seen" 在其他模块中

所以你最好去掉"namesakes"的Userform调光语句,只留下Public一个

此外,在您使用的声明语句中,每个未与特定类型明确关联的变量都隐式关联到 Variant 类型

所以在主模块中你应该使用如下的 "dimming" 语句:

Public GeoffYN As Boolean, TammyYN As Boolean, CallumYN As Boolean, JamesYN As Boolean, MickYN As Boolean, AlisonYN As Boolean, BeverlyYN As Boolean, LouiseYN As Boolean, EllenYN As Boolean


但是如果上面的所有内容都能让您继续,我还是建议您切换到 "class" 方法并使用 Dictionary 对象,如下所示

Allocator 代码窗格中放置以下代码

Option Explicit

Dim chkBoxes() As ChkBx_Class 'array of type "ChkBx_Class" which you define in a Class Module

Private Sub UserForm_Initialize()
Dim nControls As Integer, i As Integer
Dim namesArray As Variant, cbIniValues As Variant

UFInit = True

namesArray = Array("Geoff", "Tammy", "Callum", "James", "Mick", "Alison", "Beverly", "Louise", "Ellen") '<== set here the names to be associated to every CheckBox
cbIniValues = Array(True, True, True, True, False, False, False, False, False) '<== set here the initial values of checkboxes

nControls = UBound(namesArray) + 1 '<== retrieve the number of CheckBoxes you're going to consider in the Form
ReDim chkBoxes(1 To nControls) As ChkBx_Class 'redim the "ChkBx_Class" array
For i = 1 To nControls

    Set chkBoxes(i) = New ChkBx_Class 'initialize a new instance of 'ChkBoxClass' class and store it in the array i-th position
    With chkBoxes(i)
        Set .ChkBox = Me.Controls("CheckBox" & i) 'assign the correct CheckBox control to its "ChkBox" property
        .Name = namesArray(i - 1)  ' assign the Name property of the Checkbox

        .ChkBox.Value = cbIniValues(i - 1) 'set the checkbox correct initial value
         Me.Controls("Label" & i) = .Name ' set the corresponding label caption

         dealersDict.Add .Name, .ChkBox.Value ' fill the dictionary initial pair of Dealer-name/checkbox-value
    End With

Next i

Me.tbRPName.Text = ""

UFInit = False

End Sub


Private Sub cbGo_Click()

Me.Hide

End Sub

向您的项目添加一个 "Class Module"

单击 VBA IDE 主功能区菜单中的插入-> Class 模块

或右键单击 VBA IDE 项目 Window 中的任意位置并 select 在后续子菜单中插入 -> Class 模块


展开项目中的"Class Module"节点Window

如果您没有看到项目 Window,您可以通过单击主功能区菜单中的查看-> 项目 Window 打开它,或者按 "Ctrl+R"


select你添加的新Class(应该是一些"Class1"之类的)并在属性中改名为"ChkBx_Class" Window "Name" 文本框

如果您没有看到 属性 Window,您可以通过单击主功能区菜单中的查看-> 属性 Window 或按 "F4"


在 Class 模块代码窗格中放置以下内容

Option Explicit

'declare class properties: they will be associated in every instance of this class.
Public WithEvents ChkBox As MSForms.CheckBox ' "ChkBox" is now a property of the class of type CheckBox. it's associated to events
Public Name As String

' events associated to ChkBox class property
Sub ChkBox_Click()
    If Not UFInit Then dealersDict.Item(Me.Name) = Me.ChkBox.Value ' set the dictionary pair of Dealer-name/checkbox-value
End Sub

按如下方式编辑您的主要子模块

Option Explicit

Public dealersDict As New Scripting.Dictionary
Public UFInit As Boolean

Sub main()
myval = "io"
Dim myKey As Variant

Allocator.Show
Unload Allocator

For Each myKey In dealersDict
    MsgBox myKey & ": " & dealersDict(myKey)
Next myKey

End Sub

创建对 Microsoft 脚本运行时库的引用以使用字典。

这是通过在 Visual Basic 编辑器 (VBE) 中选择工具 ➜ 参考命令来完成的,它会弹出一个对话框,您可以在其列表框中找到 "Microsoft Scripting Runtime" 接下来打上复选标记,然后按确定。


运行主副

每当您需要检索与给定 name 关联的布尔值时,您只需使用

myBool = dealersDict(name)

名称可以是:

  • 具有所需名称的字符串文字 ("Alison", "Mick" , ..)

  • 一个字符串变量,其值存储想要的名称,因此您可能在代码中的某处键入:

    Dim name as string name = "Mick"


这种方法为您提供了很大的灵活性,因为您只需:

  • 在[=23=中的两个数组(namesArraycbIniValues)中设置名称及其初始布尔值]

  • 确保您有以 "CheckBox1"、"CheckBox2" 等命名的复选框,以及以 "label1"、"Label2" 命名的标签, 等等

  • 确保 "CheckBoxX" 与 "LabelX"

  • 对齐
  • 确保 namesArraycbIniValues 具有与标签和复选框相同的项目编号