代码之家  ›  专栏  ›  技术社区  ›  Smandoli

模块存在VBA错误:“找不到模块”

  •  0
  • Smandoli  · 技术社区  · 15 年前

    下面Access2003中的例程产生错误7961——我的数据库“找不到模块”。 但它只在某些模块上执行。模块发生故障的原因是一致的。
    发生了什么?

    Private Sub DoReplace()
        Dim obj As AccessObject
        For Each obj In CurrentProject.AllModules
           Debug.Print ModuleType(obj.Name) & "  " & obj.Name
        Next obj
    End Sub
    
    Public Function ModuleType(ByVal ModuleName As String) As Variant
    On Error GoTo errHandler
        Dim mdl As Module
        Set mdl = Modules(ModuleName)
        ModuleType = mdl.Type
        ModuleType = Switch(ModuleType = 0, "std     ", ModuleType = 1, "class   ")
        Set mdl = Nothing
    errExit: Exit Function
    errHandler:
            ModuleType = "Err " & Err.Number  '7961
            Resume errExit
    End Function

    调试输出:

    Err 7961  vba_28_Part_Asterisk
    class     cls_22_mas90_Item2
    Err 7961  vba_44_Part_WhereUsed2
    Err 7961  cls_22_JobOps_BOM_WhereUsed_method2
    Err 7961  vba_26_Part_misc
    std       vba_44_Part_MRP
    std       vba_99_TurnOffSubDataSheets
    Err 7961  vba_99_MasteringArraysByScott
    Err 7961  vba_44_Part_WhereUsed
    Err 7961  cls_22_JobOps_BOM_WhereUsed
    Err 7961  cls_22_mas90_Item
    class     cls_22_mas90_Order
    class     cls_23_HOMER_Item
    class     cls_44_mrp_record
    
    3 回复  |  直到 15 年前
        1
  •  5
  •   David-W-Fenton    15 年前

    我知道你已经解决了这个问题,但是你似乎没有理解为什么它会这样工作,也没有想出解决问题的最佳方法。

    在所有版本的Access中,都有几个集合可以随时使用:

    • 表格式
    • 询价
    • 形式
    • 报告

    以及其他不经常使用的:

    • 宏指令
    • 模块

    前两个集合只能作为数据库的成员访问,因此您只能通过如下方式使用TableDefs或QueryDefs集合:

      CurrentDB.TableDefs.Count
    

    这是因为TableDefs和QueryDefs是纯Jet对象,而不是访问对象。

    其他集合是访问对象的集合,它们只包括打开的对象,如果这样做,您可以看到:

      ?Forms.Count
    

    …在即时窗口中,如果没有打开的表单,无论数据库中实际有多少个表单,都会得到0。

    在访问2000之前,您必须使用文档容器来访问未加载的存储访问对象列表。这是相当复杂的,必须以不同的方式处理不同的对象类型。对于模块,代码如下:

      Dim db As DAO.Database
      Dim cnt As Container
      Dim doc As Document
    
      Set db = CurrentDb
      Set cnt = db.Containers!Modules
      For Each doc In cnt.Documents
        Debug.Print doc.Name
      Next doc
      Set doc = Nothing
      Set cnt = Nothing
      Set db = Nothing
    

    而且你还必须知道宏是存储在一个叫做“脚本”的容器中的,非常难看。

    在Access 2000中,由于Access项目的存储方式发生了变化(在系统表的单个记录中作为单个BLOB字段,而不是存储在多个记录中,每个对象一个),因此引入了currentproject.all****集合。这些是:

    • 当前项目.alldataaccesspages
    • 当前项目.allforms
    • 当前项目.allmacros
    • 当前项目.allmodules
    • 当前项目.allreports

    出于您的目的,最好的选择显然是allmodules集合而不是modules集合,因为这样您就不必担心模块是否打开。当然,容器/文档方法是可行的,但是所有模块都需要更少的代码。

    编辑:

    使用所有模块的代码是:

      Dim i As Integer
    
      For i = 0 To CurrentProject.AllModules.Count - 1
        Debug.Print CurrentProject.AllModules(i).name
      Next i
    

    或:

      Dim obj As Object
    
      For Each obj In CurrentProject.AllModules
        Debug.Print obj.name
      Next obj
      Set obj = Nothing
    

    我总是喜欢在for循环中使用强类型的对象,但是这里只有一个通用对象变量起作用,所以我可能会使用计数器,因为它节省了清理最后一个隐式对象指针的开销。

    此外,请记住,模块集合(即开放模块)包括表单模块以及独立模块和类模块,而所有模块仅限于独立模块和类模块。

        2
  •  0
  •   Smandoli    15 年前
    Set mdl = Modules(obj.Name)

    要执行上述操作,必须加载模块对象。此项检查使用

    obj.IsLoaded

    (obj是一个accessobject,mdl是一个模块——参见上文。)

    我的问题是只加载了一些模块。加载模块可以通过在VBA IDE中打开它来完成。不再出现错误7961。

    我很惊讶要得到这个答案有多困难。我不得不在谷歌上下功夫,自己动手。希望它能帮助别人。

        3
  •  0
  •   Smandoli    15 年前

    解决方案是传递accessObject(而不是字符串)。因此:

    ModuleType(ByVal ModuleName As String) As Variant
    

    …对此:

    ModuleType(ByVal obj As AccessObject) As Variant
    

    大卫的文章帮助我重新检查了代码,并提供了良好的一般知识,我将相应地投票给他的答案。然而,我的错误是关于对象和函数,而不是关于如何使用所有集合。