【问题标题】:Multiple Excel VBA routines accessing the same objects? [duplicate]访问相同对象的多个 Excel VBA 例程? [复制]
【发布时间】:2017-11-12 17:59:31
【问题描述】:

我有以下两个子程序:

Rem Attribute VBA_ModuleType=VBAModule
Sub FixPlatformsSelection()
    Dim fndList As Object
    Set fndList = CreateObject("Scripting.Dictionary")
    fndList.Add "3DO Interactive Multiplayer", "3DO"
    fndList.Add "Nintendo 3DS", "3DS"
    fndList.Add "Ajax", "AJAX"
    fndList.Add "Xerox Alto", "ALTO"
    fndList.Add "Amiga CD32", "AMI32"
    fndList.Add "Amiga", "AMI"
    fndList.Add "Apple I", "APPI"
    fndList.Add "Apple IIe", "APPIIE"
    fndList.Add "Apple IIGS", "APPGS"
    fndList.Add "Apple II Plus", "APPII+"
    fndList.Add "Apple II series", "APPII"
    fndList.Add "Apple II", "APPII"

    For Each strKey In fndList.Keys()
        Selection.Replace What:=strKey, Replacement:=fndList(strKey), _
          LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
          SearchFormat:=False, ReplaceFormat:=False
    Next strKey
End Sub

Rem Attribute VBA_ModuleType=VBAModule
Sub FixPlatformsWorkbook()
    Dim fndList As Object
    Set fndList = CreateObject("Scripting.Dictionary")
    fndList.Add "3DO Interactive Multiplayer", "3DO"
    fndList.Add "Nintendo 3DS", "3DS"
    fndList.Add "Ajax", "AJAX"
    fndList.Add "Xerox Alto", "ALTO"
    fndList.Add "Amiga CD32", "AMI32"
    fndList.Add "Amiga", "AMI"
    fndList.Add "Apple I", "APPI"
    fndList.Add "Apple IIe", "APPIIE"
    fndList.Add "Apple IIGS", "APPGS"
    fndList.Add "Apple II Plus", "APPII+"
    fndList.Add "Apple II series", "APPII"
    fndList.Add "Apple II", "APPII"

    For Each sht In ActiveWorkbook.Worksheets
    For Each strKey In fndList.Keys()
        sht.Cells.Replace What:=strKey, Replacement:=fndList(strKey), _
          LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
          SearchFormat:=False, ReplaceFormat:=False
    Next strKey
    Next sht
End Sub

如何从子例程中删除 fndList 字典并将其移动到其他位置,以便所有子例程也可以访问它?我有两个需要这个字典的例程,并且不想维护相同代码的两个副本。是否有一个特殊的地方可以在 VBA 中放置“全局”变量?谢谢。

[编辑]

我尝试将声明放在过程之外:

Public fndList As Object
Set fndList = CreateObject("Scripting.Dictionary")
fndList.Add "3DO Interactive Multiplayer", "3DO"
fndList.Add "Nintendo 3DS", "3DS"
fndList.Add "Ajax", "AJAX"
fndList.Add "Xerox Alto", "ALTO"
fndList.Add "Amiga CD32", "AMI32"
fndList.Add "Amiga", "AMI"
fndList.Add "Apple I", "APPI"
fndList.Add "Apple IIe", "APPIIE"
fndList.Add "Apple IIGS", "APPGS"
fndList.Add "Apple II Plus", "APPII+"
fndList.Add "Apple II series", "APPII"
fndList.Add "Apple II", "APPII"

Rem Attribute VBA_ModuleType=VBAModule
Sub FixPlatformsSelection()
    For Each strKey In fndList.Keys()
    Selection.Replace What:=strKey, Replacement:=fndList(strKey), _
      LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
      SearchFormat:=False, ReplaceFormat:=False
    Next strKey
End Sub

但我得到一个编译错误:无效的外部过程。

【问题讨论】:

  • 您希望字典在范围内是模块级别的吗?或者你需要它在范围内是项目级别的吗?或者您只是想将字典作为参数从一个子程序传递到另一个子程序?也许发布更多您的代码,以便我们可以就您应该使用什么做出明智的决定。
  • 它甚至需要成为字典,还是只是 Excel 中的“表格”?
  • @YowE3K 我认为使用字典比操作 Excel 对象要轻得多。
  • 我建议添加对 Microsoft Scripting Runtime 的引用;这将允许您编写 Dim dict As New Scripting.Dictionary 并将在字典的属性和方法上提供 Intellisense。
  • 添加 Microsoft Scripting Runtime 参考的目的是为了更容易编写 VBA 代码,与您如何运行宏无关。就目前而言,VBA 编辑器不知道findLst 应该指向Dictionary,具有Add 之类的方法和CompareMode 之类的属性。一旦你指定了fndList 的类型,编辑器就会警告你尝试调用不存在的方法,或者传递给方法的参数错误。

标签: excel vba


【解决方案1】:

您可以在任何SubFunction 之外创建模块级变量:

Private fndList As Scripting.Dictionary

如果您需要多个文件(AKA 模块)可以访问该变量,则将该变量声明为Public

Public fndList As Scripting.Dictionary

虽然您可以在过程之外声明变量,但您不能在过程之外执行语句(您将收到Invalid outside procedure. 错误消息)。因此,初始化代码必须在第三个Sub

Sub InitDictionary
    If Not fndList Is Nothing Then Exit Sub
    Set fndList = New Scripting.Dictionary
    fndList.Add "3DO Interactive Multiplayer", "3DO"
    fndList.Add "Nintendo 3DS", "3DS"
    fndList.Add "Ajax", "AJAX"
    fndList.Add "Xerox Alto", "ALTO"
    fndList.Add "Amiga CD32", "AMI32"
    fndList.Add "Amiga", "AMI"
    fndList.Add "Apple I", "APPI"
    fndList.Add "Apple IIe", "APPIIE"
    fndList.Add "Apple IIGS", "APPGS"
    fndList.Add "Apple II Plus", "APPII+"
    fndList.Add "Apple II series", "APPII"
    fndList.Add "Apple II", "APPII"
End Sub

如果需要,它将初始化字典。

然后,从其他每个子过程调用初始化Sub

Sub FixPlatformsSelection()
    InitDictionary

    For Each strKey In fndList.Keys()
    '...
    Next
End Sub

Sub FixPlatformsWorkbook()
    InitDictionary

    For Each sht In ActiveWorkbook.Worksheets
        '...
    Next sht
End Sub

参考资料:

【讨论】:

  • 我收到Dim fndList As Scripting.Dictionary 的“编译错误:未定义用户定义类型”错误。
  • @posfan12 - 通过 VB 编辑器中的工具->引用菜单添加对 Microsoft 脚本运行时的引用
  • @posfan12 我猜FixPlatformsSelectionFixPlatformsWorkbook 不在同一个VBA 文件中;这就是Dim(或Private)不够用的原因。
  • @postfan 在 VBA 中,每个文件都包含一个模块,每个模块仅限于一个文件。另请注意,我在 Scripting.Dictionary 和 VBA 中的范围规则上添加了指向 Microsoft 文档的链接。
  • @posfan12 这真的取决于你的具体情况。您可能希望将 Subs / Functions 的相关组组织到单独的模块/文件中,在这种情况下,您希望变量为 Public
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-23
  • 1970-01-01
相关资源
最近更新 更多