【问题标题】:How can I keep the value of this variable for my next subroutine?我怎样才能为我的下一个子程序保留这个变量的值?
【发布时间】:2012-07-06 18:22:57
【问题描述】:

我是一名初级程序员(没有经验),正在为我现在正在做的工作学习 Visual Basic。看了一天左右,终于决定开始制作所需的程序了!

但是,我遇到了一些问题。

现在我有两个子程序。第一个子例程让用户输入他们有多少数据对,以便我可以创建一个表格供他们填写。这样他们的数据就在正确的位置供我以后参考。

然后他们在完成输入数据后按下一个按钮以启动一个不同的子程序,该子程序将对他们输入的数字进行一些计算。我的问题是我需要一个变量来说明他们必须将多少数据对转移到第二个例程中。

在我继续之前,这是我到目前为止的代码! (您必须在窗口中向下滚动)我还应注意第二个子例程位于单独的模块中。

Option Explicit

Public Counter As Long


Sub TableCreation1()

    ActiveSheet.Shapes.Range(Array("Button 5")).Select

    Selection.Delete

    Counter = InputBox("How many pairs of data do you have? ")

    Range("A1") = "Time (days)"

    Range("B1") = "CFL (measured)"

    Range("A1:B1").Font.Bold = True

    Columns("A:B").EntireColumn.EntireColumn.AutoFit

    Range("A1").Select

    ActiveCell.Range("A1:B" & Counter + 1).Select

    Selection.Borders(xlDiagonalDown).LineStyle = xlNone

    Selection.Borders(xlDiagonalUp).LineStyle = xlNone

    With Selection.Borders(xlEdgeLeft)

       .LineStyle = xlContinuous

       .Weight = xlThin

    End With

    With Selection.Borders(xlEdgeTop)

        .LineStyle = xlContinuous

        .Weight = xlThin

    End With

    With Selection.Borders(xlEdgeBottom)

        .LineStyle = xlContinuous

        .Weight = xlThin

    End With

    With Selection.Borders(xlEdgeRight)

        .LineStyle = xlContinuous

        .Weight = xlThin

    End With

    With Selection.Borders(xlInsideVertical)

        .LineStyle = xlContinuous

        .Weight = xlThin

    End With

    With Selection.Borders(xlInsideHorizontal)

        .LineStyle = xlContinuous

        .Weight = xlThin

    End With

    Dim btn As Button

    Dim rng As Range

    With Worksheets("Sheet1")

        Set rng = .Range("A" & Counter + 2)

        Set btn = .Buttons.Add(rng.Left, rng.Top, rng.Width, rng.Height)

    With btn

        .Caption = "Click this button to begin calculations"

        .AutoSize = True

    End With

    End With

End Sub



Option Explicit

Dim IntermediateVariable As Long

Public Counter As Long

Sub FindCFLGuess()

IntermediateVariable = Worksheets("Sheet1").Range("B:B").Cells.SpecialCells(xlCellTypeConstants).Count

Counter = IntermediateVariable - 1

End Sub

为什么 Counter 的值不能延续到第二个子例程?现在我有一个解决方法来计算 B 列中填写的单元格数量,这给了我数字。但是,这使得我无法将 B 列中的任何空间用于我想要使用的工作表的其余部分。

有人可以帮忙吗?我认为“公共”会使其成为工作簿级别的变量?每当我让第二个子显示 Counter 的值时,它就会显示为零。

抱歉,如果我的代码混乱/效率低下。我还在学习。 :)

【问题讨论】:

  • 对于初学者,您要声明 Counter 两次。尝试摆脱第二个定义。 Public Counter As Long
  • 当我尝试运行上面编写的代码时,由于Option Explicit 和中间声明的公共变量,我得到一个编译错误。你怎么能运行它来知道它不工作?

标签: vba excel scope


【解决方案1】:

在您的代码中,您声明了两次Public Counter As Long。可能发生的情况是,您的每个 Sub 块都获得了不同的 Counter 变量。如果您删除第二个,它们应该共享相同的变量。

此外,您应该只需要在每个模块中列出一次Option Explicit。其中,现在我看到您指定这些是单独的模块,您做得很好。

编辑:试图阐明更多。

将其视为一个分层,每个“范围”都是该层可以访问的。每一层都可以访问自己和所有父级。这是一个简化的可视化:

( program 
    ( module
        ( sub )
    )
)

在你的子程序中你引用了变量,所以程序开始向上看。当然假设您设置了Option Explicit,这意味着必须手动定义变量,并且永远不会自动定义它们。

您想要的内容类似于以下内容。变量在范围内是全局的,以便可以从同时运行的其他模块访问。

( program
    [global variable]
    ( module1
        ( sub )
    )
    ( module2 )
)

【讨论】:

  • 谢谢!我多年来一直在编写 VBA,但从未完全理解这个概念!
  • @Scott 在两个例程范围之外声明的变量应该具有持续的生命周期和可见性,并且在两个例程中都可以访问。我并没有很好地解释这一点,这是很好的补充信息! msdn.microsoft.com/en-us/library/1t0wsc67.aspx
  • 我只需要使用一次 Option Explicit,即使两个部分都在不同的模块中?即使我删除了第二个公共计数器 As Long,我的代码仍然显示为零。我最终将值放入 Z1。但这感觉像是一种廉价的方法。
  • @user1506937 这些在不同的模块中?这确实是一个不同的问题。您不应该在帖子中将它们分组,我想我在阅读时掩盖了关于它们是独立模块的部分。
  • 但我只是在单独的模块中测试了这个概念。您确实需要在两个模块中使用 Option Explicit,但不需要变量声明。在第二个模块中没有 Option Explicit 时,变量变为零。
【解决方案2】:

我删除了您在生产中可能需要的一堆无关代码,但只是妨碍了您发现问题。我测试了以下内容,并且 Counter 将其在第一个模块中的第一个 sub 中设置的值保持为第二个模块中的 sub。

模块 1:

Option Explicit

    Public Counter As Long

    Sub TableCreation1()
        Dim btn As Button
        Dim rng As Range

        Counter = InputBox("How many pairs of data do you have? ")
        Range("A1") = "Time (days)"
        Range("B1") = "CFL (measured)"
        Range("A1:B1").Font.Bold = True
        Columns("A:B").EntireColumn.EntireColumn.AutoFit
        Range("A1").Select
        ActiveCell.Range("A1:B" & Counter + 1).Select

        With Worksheets("Sheet1")
            Set rng = .Range("A" & Counter + 2)
            Set btn = .Buttons.Add(rng.Left, rng.Top, rng.Width, rng.Height)
            With btn
                .Caption = "Click this button to begin calculations"
                .AutoSize = True
            End With
        End With
    End Sub

模块 2:

Option Explicit

Sub FindCFLGuess()
    MsgBox ("Counter = " & Counter)
End Sub

如果您创建一个包含 2 个模块的新工作簿并将代码粘贴到每个模块中,如果您依次运行 TableCreation1FindCFLGuess,您的 Counter 变量的值将显示在 messagebox 中。

如果由于某种原因出现运行时错误,或者中断代码的执行,显然 Counter 将失去其价值。如果这些事情都没有发生,你应该添加一个手表 在您单步执行代码时跟踪变量的值。

要添加监视,请右键单击变量,选择添加监视...,然后从模块下拉列表中选择(所有模块)。当表达式的值发生变化时,您还可以让手表中断。

【讨论】:

  • 天哪,我直到现在才看到这个。这很有帮助,谢谢!我不知道在每个模块中声明变量是在重置值。
  • 好交易——很高兴它有帮助。您是否让您的代码按照您想要的方式工作?
猜你喜欢
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多