在 .xlam 和 .xlsm 文件之间传递公共变量

Passing Public variable between .xlam and .xlsm files

提问人:Martin 提问时间:11/8/2023 更新时间:11/8/2023 访问量:52

问:

我正在从功能区 *.xlam (file1) 运行一个查找函数,该函数打开一个包含所有项目宏 (file2) 的远程 *.xlsm 文件,该文件又在远程数据库 (file3) 上运行查找代码。

File2 创建一个变量“Confirm”字符串,该字符串在显示为 Msgbox 时效果很好 - 但 msgbox 是模态的并停止代码。这意味着当 file2 保持打开状态时,其他用户将没有对 file3 的写入权限。

为了解决这个问题,我在 file1 上创建了一个用户窗体来模仿 file2 中的 msgbox。 一切正常,file2 和 3 按预期打开和关闭,但 file2 的变量“Confirm”未传递到 File1 的用户窗体标签。

下面的压缩代码。 任何帮助都非常感谢!

File1 *.xlam 代码:

Public Confirm As String

Sub ViewSUB(control As IRibbonControl)
    Dim Sub_Macros As String, strFileExistsA As String, strFileExistsB As String
    Dim currentWorkbook As Workbook
    
            strFileExistsA = Dir(Sub_Macros_L)
            strFileExistsB = Dir(Sub_Macros_R)
                If strFileExistsA <> "" Then
                   Sub_Macros = Sub_Macros_L
                ElseIf strFileExistsB <> "" Then
                   Sub_Macros = Sub_Macros_R
                Else
                    MsgBox "Macro File is missing", vbCritical, "Macro File Missing"
                    Exit Sub
                End If
        Application.ScreenUpdating = False
        Application.Calculation = xlManual
        Set currentWorkbook = Application.ActiveWorkbook
        Workbooks.Open Sub_Macros, ReadOnly:=True
        currentWorkbook.Activate
        Application.Run ("'Macros.xlsm'!ViewSUB")
        
    ViewSub_Details.Show vbModeless
    
        Workbooks("Macros.xlsm").Close SaveChanges:=False
        Application.Calculation = xlAutomatic
        Application.ScreenUpdating = True
End Sub

File2 只是创建字符串,我可以证明它适用于 msgbox。 这只是该代码的一部分:

Public Confirm As String
        For i = 3 To LastrowDBase
            If DBase.Cells(i, 2) = SUBPN And DBase.Cells(i, 5) = "SomeText" Then
                Confirm = Confirm & "  - " & DBase.Cells(i, 3) & " - Flag: " & DBase.Cells(i, 7) & " - " & DBase.Cells(i, 6) & vbCrLf
            End If
        Next i
        
            MsgBox Confirm

然后返回 File1 的用户窗体代码:

Option Explicit

Private Sub UserForm_Initialize()

    Label1.Caption = Confirm
    
End Sub

Private Sub CommandButton01_Click()

    Unload ViewSub_Details

End Sub
Excel VBA 变量 public

评论


答:

0赞 Black cat 11/8/2023 #1

这些引文来自 Excel 帮助文件

公共 使用 Public 语句声明的变量对所有应用程序的所有模块中的所有过程都是可见的,除非 Option Private Module 有效。在这种情况下,变量仅在它们所在的项目中是公共的。

引用项目 您直接从当前正在处理的项目创建链接的项目。由当前项目的某个直接引用的项目引用的项目称为间接引用的项目。当前项目无法访问其公共变量,除非通过其项目名称进行限定。项目之间的直接引用和间接引用的任何组合都是有效的,只要它们不会导致一个完整的周期。

引用项目 当前项目。如何创建指向项目的链接取决于宿主应用程序。例如,若要在 Microsoft Excel 中直接引用项目,请从“工具”菜单的“引用”对话框中选择该项目。直接引用项目中的公共变量对直接引用的项目可见,但直接引用项目中的公共变量对直接引用的项目不可见。

定义公共模块级作用域 如果将模块级变量声明为公共变量,则该变量可用于项目中的所有过程。在以下示例中,字符串变量

strMsg

可由项目中任何模块中的任何过程使用。

包含在模块的“声明”部分中。

将 strMsg 作为字符串的公共 strMsg

默认情况下,除事件过程外,所有过程都是公开的。当 Visual Basic 创建事件过程时,会自动在过程声明之前插入 Private 关键字。对于所有其他过程,如果不希望该过程是公共的,则必须使用 Private 关键字显式声明该过程。

可以使用引用项目中的标准模块或类模块中定义的公共过程、变量和常量。但是,必须首先设置对定义它们的项目的引用

在标准模块或类模块(如窗体模块或报表模块)之外定义的公共过程、变量和常量不可用于引用项目,因为这些模块对于它们所在的项目是私有的。

1赞 FaneDuru 11/8/2023 #2

如果不引用相应的工作簿,并且工作簿中没有相同的变量,则无法直接从其他工作簿中读取变量。但是,您可以在不引用工作簿的情况下执行此操作,即使讨论中的变量被声明为 Private,调用返回相应变量的函数:Public

  1. 在需要从中读取变量的工作簿的标准模块中,复制以下代码:
Option Explicit

Private myVar As String 'the variable to be returned in another workbook...

Sub GiveMyVarValue()
   myVar = "test variable"
End Sub

Public Function GetMyvar() As String 'PUBLIC function!
   GetMyvar = myVar
End Function

并运行以为相应的变量提供值(当然,您可以使用现有的过程/变量,但请注意将其作为函数的返回值。GiveMyVarValueGetMyvar

  1. 使用活动工作簿中的下一个代码,从另一个工作簿中读取变量:
Sub ReadVariableFromDifferentWB()
  Dim wb As Workbook: Set wb = Workbooks("Personal.xlsb") 'use here the real workbook name where from you need to return the variable
  Dim x As String
  
  x = Application.Run("'" & wb.name & "'!GetMyVar")
  MsgBox x
End Sub

请在测试上述建议的解决方案后发送一些反馈,我需要时多次使用该解决方案......

评论

0赞 Martin 11/9/2023
我遵循了你的建议,它有效,然后将其集成到我的项目中,它有效!希望我得到正确的格式: 对于用户窗体: 和 Macro.xlsm 文件中: ' 公共函数 GetMyvar() 作为字符串 GetMyvar = 确认结束函数'Option Explicit Private Sub UserForm_Initialize() Dim wb As Workbook: Set wb = Workbooks("Macros.xlsm") Label1.Caption = Application.Run("'" & wb.Name & "'!GetMyVar") End Sub
1赞 FunThomas 11/8/2023 #3

您无法访问项目外部的变量(项目基本上是您的 Excel 文件)。您的变量是不同的变量,file1 无法访问 file2。该关键字表示该变量在 file2 的整个项目中是全局变量(因此 file2 的所有模块都可以访问它),但对任何其他正在运行的 VBA 代码都不是公共的。confirmconfirmpublic

但是,您可以做的是提供字符串作为函数的结果:confirm

Public Function GetConfirmString
    For i = 3 To LastrowDBase
        If DBase.Cells(i, 2) = SUBPN And DBase.Cells(i, 5) = "SomeText" Then
            Confirm = Confirm & "  - " & DBase.Cells(i, 3) & " - Flag: " & DBase.Cells(i, 7) & " - " & DBase.Cells(i, 6) & vbCrLf
        End If
    Next i
    GetConfirmString = Confirm
End Function

您可以使用以下命令调用此函数:Application.Run

Private Sub UserForm_Initialize()
    Label1.Caption = Application.Run ("'Macros.xlsm'!GetConfirmString")
End Sub

评论

0赞 Martin 11/9/2023
我相信这与上面的解决方案非常相似,并且更符合我最终如何让它工作。尽管如此,还是谢谢你!