试图在VBA Excel中找出变量范围?

时间:2015-09-06 15:45:01

标签: vba excel-vba excel

我使用SpinButton和Label创建了一个Userform。当用户点击Spinup时,它会增加一个变量,然后将该索引从数组显示到标签。或者使用SpinDown的另一种方式。我一直遇到的问题是当我尝试使用模块中的变量来递增或递减以调整数组的索引时。我试过这种方式:

Private Sub SpinButtonM_SpinDown()
    Dim Counter As Integer
    Dim a As Integer

    a = 1
    Counter = Counter - a

    UserForm2.Month.Caption = Counter
End Sub

我试过这种方式似乎都给了我错误:

Private Sub SpinButtonM_SpinDown()
    Dim monthArray

    monthArray = Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep",...)

    Module1.Counter = Module1.Counter + 1
    UserForm2.Month.Caption = Module.Counter
End Sub

2 个答案:

答案 0 :(得分:2)

要在Module1中声明它时使Counter在userform中工作,您需要在Module1中将其声明为Public。这为整个项目设定了范围。

我没有理由将任何变量放在userform之外,而是为了使你的循环月旋转器工作并使用Module1中的变量,这就是我要做的:

在Module1中,放置此代码:

Option Explicit

Public Counter As Long
Public monthArray As Variant

在userform中,放置以下代码:

Option Explicit

Private Sub SpinButtonM_SpinUp()
    UpdateMonth 1
End Sub
Private Sub SpinButtonM_SpinDown()
    UpdateMonth -1
End Sub

Private Sub UpdateMonth(Delta As Long)
    Counter = Counter + Delta
    If Counter < 1 Then Counter = 12
    If Counter > 12 Then Counter = 1
    Month = monthArray(Counter)
End Sub

Private Sub UserForm_Initialize()
    monthArray = [transpose(text(date(,row(1:12),1),"mmm"))]
    UpdateMonth 1
End Sub

注意:这假定Month是标签的名称。

注意:不是使用Module1中的全局变量,而是在您的场景中将其范围限制为userform并将其声明为Private是更有意义的。您可以将它们直接放在userform代码模块中的Option Explicit下,并将Public替换为每个变量的Private。然后你不需要Module1 ......至少对于问题中描述的内容。

注意:作为将Module1中的任何变量设置为Public的副作用(这使得它们在userform中可用)关闭userform并不会结束程序。当您重新打开表单时,月份不会在Jan上。相反,它将是用户窗体关闭时的位置,加上一个。要覆盖该行为,您需要向用户表单添加UserForm_Terminate()过程并在其中放置End语句。这将强制程序在用户窗体关闭时结束。但是,遵循将变量重新调整为用户形式的建议完全消除了这种副作用,这意味着您根本不需要UserForm_Terminate()过程。

<强>更新

在回复您的注释时,要更改此解决方案以便在程序运行之间保留微调器显示的当前月份,即使工作簿已关闭然后重新打开,您也需要在每次微调器更改时保存当前月份。一种干净的方法是将Counter值存储为命名常量。与任何已定义的名称一样,此命名常量可通过工作表中的名称管理器(Control-F3)进行检查。

请注意,我们存储的命名常量的名称是_CounterMemory

Private Sub SpinButtonM_SpinDown()
    UpdateMonth -1
End Sub
Private Sub SpinButtonM_SpinUp()
    UpdateMonth 1
End Sub

Private Sub UpdateMonth(Delta As Long)
    Counter = Counter + Delta
    If Counter < 1 Then Counter = 12
    If Counter > 12 Then Counter = 1
    Month = monthArray(Counter)
    ThisWorkbook.Names.Add "_CounterMemory", Counter
End Sub

Private Sub UserForm_Initialize()
    Dim n&
    monthArray = [transpose(text(date(,row(1:12),1),"mmm"))]
    On Error Resume Next
    n = [_CounterMemory]
    If n = 0 Then n = 1
    Counter = n
    UpdateMonth 0
End Sub

与将值存储在工作表中的单元格中相比,此路线的众多优点之一是自由裁量权。这是不合适的。它不容易受到正常的用户篡改,因为绝大多数普通用户不知道名称管理器。如果删除工作表,则不会对此解决方案产生任何影响。这是一种促进变量持久性的简洁方法。

作为澄清说明,命名常量与使用CONST语句在VBA模块中声明的常量不同。相反,命名常量类似于工作表上的命名范围,但不是命名范围,而是命名一个文字值(换句话说,一个常量值)。但我们可以从VBA代码中创建和读取该值,这正是我的更新所做的。

答案 1 :(得分:0)

如果它们在子或函数内声明,则只能在该子函数或函数中使用。一旦你离开这个功能,它就消失了。

如果您在模块或表单级别声明它们,则可以在整个模块或表单中访问它们。

Option explicit
Private strA as string

Sub test()
    Dim strB As String

    strA = "A"
    strB = "B"

    Test2
End Sub

Sub Test2()
    msgbox strA

    'msgbox strB This will not work as it is only available for sub test
End Sub

所以你可能想要移动

Dim Counter As Integer

到代码的最顶层。

在此处查看一些信息https://support.microsoft.com/en-us/kb/141693