Excel 全局变量在不同子系统中不可访问?

Excel 全局变量在不同子系统中不可访问?,excel,vba,userform,Excel,Vba,Userform,我在模块1的顶部全局声明了projname。它在userform中分配,并在createWB子系统中成功访问。但是,当我在模块1的addWindow子系统中访问它时,它变为空(“”)。我不确定为什么会发生这种情况,因为我认为既然变量是全局声明的,我应该能够在任何子类中访问它 单元1 Option Explicit Public outputWorkbook As Workbook Public globalcounter As Integer Public projname As String

我在模块1的顶部全局声明了projname。它在userform中分配,并在createWB子系统中成功访问。但是,当我在模块1的addWindow子系统中访问它时,它变为空(“”)。我不确定为什么会发生这种情况,因为我认为既然变量是全局声明的,我应该能够在任何子类中访问它

单元1

Option Explicit

Public outputWorkbook As Workbook
Public globalcounter As Integer
Public projname As String
Public projnum As String

createWB()
    Dim uf2 As New UserForm2
    uf2.Show

    Set outputWorkbook = Workbooks.Add(xlWBATWorksheet)
    outputWorkbook.SaveAs Filename:=Environ("userprofile") & "\Desktop\" & 
    Replace(projname, " ", "") & ".xlsx"

    outputWorkbook.Activate

    Range("B3") = projname
    Range("B4") = projnum
End Sub

addWindow()
    Workbooks(Replace(projname, " ", "") + ".xlsx").Activate
End Sub
用户表单代码

Public Sub CommandButton1_Click()
    projname = Me.TextBox1.Text
    projnum = Me.TextBox2.Text
    Me.Hide
End Sub

单元格
B3
B4
分配了正确的值,但是
addWindow()
行会导致下标超出范围错误。当我用
Debug.Print
测试它时,我看到projname=”“。我还简单地尝试了
outputWorkbook.Activate
,这也不起作用。

您可以尝试使用Module1作为前缀吗,就像这个代码一样

 Public Sub CommandButton1_Click()
        Module1.projname = Me.TextBox1.Text
        Module1.projnum = Me.TextBox2.Text
        Me.Hide
    End Sub
避免全球污染 除非有很好的理由使用它们,否则请尝试使用它们。我们希望避免污染全局名称空间行星船长警告过我们这一点

相反,尝试在需要时通过各种方法传递参数。这有助于防止错误,使代码更容易理解,并利用组合


使用用户表单存储和公开属性 尝试使用
With
语句实例化您的用户表单,这样您就有了它的一个捕获实例,您可以访问它公开的各种属性。在您的情况下,
ProjectName
ProjectNumber

此外,应该有一个属性来检查userform是否被取消或按下了
X
按钮

您的userform将如下所示:

Option Explicit

Private cancelled As Boolean

Public Property Get ProjectName() As String
    ProjectName = TextBox1.Value
End Property

Public Property Get ProjectNumber() As Long
    ProjectNumber = TextBox2.Value
End Property

Public Property Get IsCancelled() As Boolean
    IsCancelled = cancelled
End Property

Private Sub CommandButton1_Click()
    Me.Hide
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = VbQueryClose.vbFormControlMenu Then
        Cancel = True
        OnCancel
    End If
End Sub

Private Sub OnCancel()
    cancelled = True
    Hide
End Sub

实例化用户表单 下面是现在调用您的userform的示例(请将名称从Userform2更改)。请注意,我们正在使用
With
块捕获您的userform实例。在此块中,我们可以访问我们公开的属性:
ProjectName
ProjectNumber
IsCancelled

Private Sub createWB()
    With New UserForm2
        .Show
        If Not .IsCancelled Then
            ' Do neccessaray steps here...

            ' You have access to ProjectName and Project number.
            ' Pass this to your addWindow method.
            addWindow .ProjectName

        End If
    End With
End Sub
现在可以从用户表单访问
ProjectName
,并将其作为参数传递给
addWindow
方法

Private Sub addWindow(ByVal projName As String)
    Workbooks(Replace(projName, " ", "") + ".xlsx").Activate
End Sub


有关以这种方式使用userforms的更多信息,请参阅此帮助。

听起来projname的作用域是模块1,而不是全局的-您能显示您的声明吗?我刚刚添加了它!
.SaveAs
方法能否重置全局变量?我认为最重要的是如何/在何处调用
addWindow()
。如果您在整个过程之外调用它,那么
projName
将是
”。例如,如果在运行
creatWB
时包含调用者,则将存储
projName
,您将能够访问它。是的,问题存在,因为您似乎将它们作为独立进程调用。如果将
calladdwindow
包含到
createWb()
中,您将看到不会出现该错误,因为该信息是基于
createWb()
例程存储的。否则它只是将默认状态返回为“”