2015-09-06 12 views
1

我用SpinButton和Label做了一个Userform。当用户点击Spinup时,它会增加一个变量,然后将该索引从数组显示到标签。或者与SpinDown的其他方式。我遇到的问题是当我尝试使用模块中的变量来递增或递减来调整数组的索引时。我试着这样说:试图找出VBA Excel中的变量作用域?

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

模块1计数器和模块计数器是相同的变量吗?您是否在代码的一开始就使用[Option Explicit](http://www.excel-easy.com/vba/examples/option-explicit.html)? – dee

+0

是的,他们是相同的,没有不必要尝试明确的选项。 –

+0

@pnuts谁决定标记规则需要重新考虑。目前的指导方针很荒谬。它说:“*将Excel标签与r,VSTO,C#,VB.NET,PowerShell,OLE自动化以及其他与编程有关的标签和问题结合起来。*”因此,将完全外部的东西添加到“Excel”标签,但将VBA与Excel标签结合是不行的?这具有将完全分类为Excel的相关问题(具有VBA组件甚至不是Excel的一部分)的效果。这些问题没有在“Excel”搜索中列出。 VBA是Excel的一个组成部分。 –

回答

2

一些信息要获得Counter到用户窗体中工作,而在模块1声明它,你需要将其声明为公共的模块1。这设定了整个项目的范围。

我看不出有什么理由将用户窗体之外的任何变量放在你正在做的事情之外,但为了让你的循环月份微调工作并使用Module1中的变量,那么这就是我所要做的:

在模块1,将此代码:

Option Explicit 

Public Counter As Long 
Public monthArray As Variant 

而且在用户窗体,将此代码:

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的全局变量,在您的场景中将其范围限制为用户窗体并将其声明为“私有”会更有意义。您可以通过将它们直接放置在用户表单代码模块中的Option Explicit下,并将Public替换为每个变量的Private。那么你不需要Module1 ......至少在问题中描述了什么。

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

UPDATE

在回答您的意见,以使通过微调显示当月被保留之间的程序运行,即使在关闭工作簿,然后重新打开改变这个解决方案,您需要保存每当微调控制器改变时的当前月份。干净的方法是将Counter值存储为命名常量。和任何Defined Name一样,这个命名常量将可以通过工作表中的Name Manager(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代码创建和读取这个值,这正是我的更新所做的。

+0

嗨ExcelHero请你解释代码'[转置(文本(日期(,行(1:12),1),“mmm”))]'我被这个迷失了。 – HarveyFrench

+0

@哈维法国哈维你好。这只是一个简单的数组公式。要测试它,请复制公式(但不要包围它的方括号)并转到任何工作表。选择12个单元格的任何垂直范围,然后在Excel顶部的公式栏中输入一个等号,然后粘贴公式。用Control-Shift-Enter确认。您会看到公式中TEXT()函数格式化的12个月。这是OP想要的格式。 –

+0

感谢您的信息。该程序将在同一个月内多次使用,因此如果能够保持在同一个月内就可以正常工作。 –

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