VBA 2关于可变范围和寿命的问题

时间:2012-03-23 20:51:57

标签: vba module scope

关于变量的范围和生命周期,我正在尝试使用VBA进行两个问题。

  1. 我有不同的潜水员一遍又一遍地使用相同的变量。例如,一个整数,将列定义为日期列,cDate或app作为Application。由于我有一个相当大的声明部分,我想把它放在一个单独的模块中使用Global,但这不起作用。我在这里如何设置程序范围是否重要?我怎么能这样做?

  2. 与Q1类似,初始化变量怎么样?具体来说,我没有复制和粘贴找到列标题的同一个块(例如cDate),而是将其放入自己的过程中。我正在试图解决许多问题。我希望这是可能的,也许不是。

  3. 告诉我你是否需要查看代码。告诉我你想看到什么,我把它扔到这里。 (PS-我已经通过了VBA帮助,MSDN,Goole等,这里有一些我不理解的东西)

    编辑:添加已编辑的代码,因为真实的东西很长。所有部分都在单独的标准模块中。我读过全局声明只能在工作簿级别及以下工作,因此我也尝试在每个模块中声明并设置appwbwrkPublic(不是如下所示): 这是我的声明:

    Option Explicit
    
    Global app As Application
    Global wb As Workbook
    Global wrk As Worksheet
    
    Global cInvoice As Byte
    
    Global iEndCol As Integer
    Global lEndRow As Long
    Global x As Integer
    
    Global sString1 As String
    
    Global rng As Range
    
    Private Sub Not_Really_a_sub()
        'No code. I read that any declaration needed to be in a module 
        ' with a procedure. I tried it with out the dummy sub also
    End Sub
     'green text, read me and notes
    

    执行调用的子程序:

       Dim modulevariables As Integer
    
    Sub Calling_Sub()
    
     'doing things
    
     lEndRow = 1 'blah blah blah
     iEndCol = 1 ' blah blah blah
     app.Run "'" & ThisWorkbook.Name & "'!Header_Finder"
    
      'Code using cInvoice etc.
    
    End Sub
    

    Header finder:

    Private Sub Header_Finder()
      With wb.ActiveSheet
        For x = 1 To iEndCol
            If InStr(UCase(.Cells(x, 1)), UCase("Invoice")) > 0 Then
                cInvoice = x
            ElseIf .Cells(1, x) = "next thing" Then
                cNextThing = x
            End If
        Next
     End With
    End Sub
    

    谢谢。

3 个答案:

答案 0 :(得分:2)

因为这与我的其他(非)答案无关,但我需要再次提供一些代码,我会把它放在这里。

在“变量”模块中,您声明变量:

dim wb as Workbook

在使用此变量之前,您必须初始化它,即给它一个值(这些示例中的任何一个都可以使用,每个示例都适用于不同的场景):

set wb = ThisWorkbook
set wb = ActiveWorkbook
set wb = Application.Workbooks(1)

如果 在访问之前初始化此变量,就像在此示例中一样:

dim wb as Workbook
debug.print wb.name

您将收到错误:“运行时错误'91':对象变量或未设置块变量”

只有对象变量需要初始化。其他数据类型则没有。简单地说,非对象数据类型如下。默认值(在声明时初始化)在括号中:

  • 整数[0]
  • 长[0]
  • String [“”]
  • Double [0]
  • 单[0]
  • 日期[0,或1899年12月30日]
  • Byte [0]
  • 布尔值[错误]
  • 货币[$ 0]

其他一切都是一个对象,需要某种初始化。一个例子如下:

Option Explicit

Dim wb as Workbook
Dim app as Excel.Application
Dim wrk as Worksheet

Set app = Application
Set wb = app.workbooks(1)
Set wrk = wb.sheets(1)

'If any of the lines preceding this line are skipped, an error will occur.
debug.print wrk.name

很抱歉,如果您已经知道这一点(我真的,我要写的很多!)只是想在上面的评论讨论之后确保我们在同一页上。

答案 1 :(得分:1)

Q1。

您可以在三个不同级别声明变量。程序级别(听起来像您一直在做的并希望远离),模块级别或项目级别。

要在模块级别声明变量,只需在第一个过程之外声明它,例如

Dim app As Application

Sub mySub()
...

该变量可供模块内的所有程序使用。要使变量可用于其他模块中的过程,您可以使用公共声明,例如

Public app As Application

Sub mySub()
....

Q2。

如果有一个过程初始化可以根据需要从其他过程调用的变量,那么最简单的方法是这样做。例如,下面的代码创建了一个名为PubStr的公共变量,在第一个从第二个过程调用的过程中对其进行初始化。

Option Explicit
Public PubStr As String

Sub InitVar()
PubStr = "Hello World!"
End Sub

Sub RunMe()
Call InitVar
MsgBox PubStr
End Sub

运行“RunMe”将调用InitVar过程,该过程初始化公共变量PubStr。

希望这有帮助。

答案 2 :(得分:1)

不是真正的答案,但我需要包含一些代码。作为测试,我将以下代码放在一个模块(Module1)中:

Public wb As Workbook

这个代码在另一个模块(Module2)中:

Sub test()

    Set wb = ThisWorkbook
    Debug.Print wb.Name

End Sub

这对我来说很好。您是否可以尝试在新工作簿中执行相同操作并让我知道它是如何进行的?此外,您可以尝试更明确地指定您引用的变量,如此(仍在Module2中):

Sub test()

    Set wb = ThisWorkbook
    Debug.Print Module1.wb.Name

End Sub