将Access.Application对象传递给函数:Dim,Set,Object如何使其工作?

时间:2015-07-13 23:41:05

标签: ms-access access-vba pass-by-reference currying

我在Stack Overflow页面中遇到了这个(修改过的)函数,并试图让它工作而不放弃传递的对象(如果我在第一个例程中严格处理Access.Application它将工作)。

是的我知道有很多方法可以得到相同的答案(主要来自堆栈上的其他帖子),但是这里有一个将对象传递给我想要掌握的函数的一般概念 - 请忘记该函数检查表的存在。

 
Function FCN_CheckTblsExist(theDatabase As Access.Application, _
tableName As String) As Boolean  

'access.Application.CurrentData.AllTables.Count
'etc is the 'workaround enabling disposal of 
'the "theDatabase" object variable

    ' Presume that table does not exist.
    FCN_CheckTblsExist = False

    ' Define iterator to query the object model.
    Dim iTable As Integer

    ' Loop through object catalogue and compare with search term.


    For iTable = 0 To theDatabase.CurrentData.AllTables.Count - 1
        If theDatabase.CurrentData.AllTables(iTable).Name = tableName Then
            FCN_CheckTblsExist = True
            Exit Function
        End If
    Next iTable


End Function


Function callFCN_CheckTblsExist(tableName As String)  
'this is an example of a curried function?--step down in dimensionality

Dim bo0 As String    
Dim A As Object
Set A = CreateObject("Access.Application")

bo0 = FCN_CheckTblsExist(A, tableName)

MsgBox tableName & " Exists is " & bo0

End Function

我不知道(theDatabase As Access.Application,。)部分是否正确,这可能是问题的根源,而不是可能需要的Dim,Set,Object(New?)体操在辅助程序中。也许存在参考库问题(我正在运行Access 2013)。

更新:我不确定以下是否足够强大,但这就是我之前在帖子中所说的内容,这只是为了完整性而放在这里。顺便说一句,这不是一个拆分应用程序,所以也许这就是为什么以下工作。我很欣赏HansUp的帖子,关于这个问题还不够。反正

Public Function FCN_CheckTblsExist(tableName As String) As Boolean   'Call this function once for every table

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim appAccess As New Access.Application
Dim theDatabase As Access.Application

    ' Presume that table does not exist.
    FCN_CheckTblsExist = False

    ' Define iterator to query the object model.
    Dim iTable As Integer

    For iTable = 0 To Access.Application.CurrentData.AllTables.Count - 1
        If Access.Application.CurrentData.AllTables(iTable).Name = tableName Then
            FCN_CheckTblsExist = True
            Exit Function
        End If
    Next iTable

End Function

只是想补充一点,我在技术上发布的这个最后一个函数将被视为部分或不干扰,具体取决于通过调用" Access.Application.CurrentData.AllTables来限制函数的范围。&#34 34;作为" theDatabase"的替代,只将Access.Application.CurrentDb.Name创建的特定字符串替换为原始函数...(数据库,...这将是一个真正的完全currying。

无论如何将对象传递给函数,库和它们的方法是本讨论的主要焦点。当我得到DAO问题时,我应该对可能发生的事情有更好的感觉,然后我会相应地发布并标记最佳解决方案。

2 个答案:

答案 0 :(得分:2)

问题不在于将Access.Application对象传递给其他函数。而是创建Access.Application,然后检查是否存在表,而无需在该Access会话中打开数据库。在这种情况下,theDatabase.CurrentData.AllTables.Count应该触发错误 2467,“您输入的表达式是指已关闭或不存在的对象。”

我修改了这两个程序并在Access 2010中对它们进行了测试。编译和运行都没有错误,并产生我认为你想要的结果。

Function FCN_CheckTblsExist(theDatabase As Access.Application, _
        tableName As String) As Boolean

    Dim tdf As DAO.TableDef
    Dim blnReturn As Boolean

    blnReturn = False
    For Each tdf In theDatabase.CurrentDb.TableDefs
        If tdf.Name = tableName Then
            blnReturn = True
            Exit For
        End If
    Next ' tdf
    FCN_CheckTblsExist = blnReturn
End Function

Function callFCN_CheckTblsExist(DbPath As String, tableName As String)
    Dim bo0 As Boolean
    Dim A As Object

    Set A = CreateObject("Access.Application")
    A.OpenCurrentDatabase DbPath
    bo0 = FCN_CheckTblsExist(A, tableName)
    MsgBox tableName & " Exists is " & bo0
    Debug.Print tableName & " Exists is " & bo0
    A.Quit
    Set A = Nothing
End Function

注意在尝试打开 DbPath 数据库之前,我没有包含任何检查 DbPath 数据库的规定。因此,如果为数据库提供不存在的路径,则会出现错误。

DAO参考问题

DAO 3.6 是最旧的DAO系列。它仅支持较旧的MDB类型数据库。当Access 2007引入ACCDB数据库类型时,引入了新的DAO库( Access数据库引擎对象库,有时称为 ACEDAO )。除了支持ACCDB数据库, ACEDAO 还可以支持较旧的MDB类型。

设置引用时,请勿尝试同时选择它们。

以下是我的项目参考的截图:

VBE Project References

当我在立即窗口中检查我的项目引用时,请注意 ACEDAO 甚至被称为 DAO 。我还运行了 callFCN_CheckTblsExist 过程来演示它在没有 DAO 3.6 引用的情况下工作:

enter image description here

这完全基于Access 2010.您使用的是Access 2013,因此您的 ACEDAO 版本号可能会有所不同,但其他所有内容都应该相同。

答案 1 :(得分:1)

以下是一些解决方案以及检查表是否存在的更简单方法:

<强>工作区/数据库; (比使用应用程序快得多)

Function TestFunction_DataBase()
  Dim ws As Workspace
  Dim db As Database

  Set ws = CreateWorkspace("", "admin", "", "dbUseJet")
  Set db = ws.OpenDatabase("the db path", , , CurrentProject.Connection)

  MsgBox TdefExists_DataBase(db, "the table name")

  db.Close
  ws.Close
  Set db = Nothing
  Set ws = Nothing

End Function

Function TdefExists_DataBase(ac As Database, strTableName As String) As Boolean
  'check to see if table exists
  On Error GoTo ErrHandler
  Dim strBS As String

  strBS = ac.TableDefs(strTableName).Name
  TdefExists_DataBase = True
  Exit Function
ErrHandler:
  TdefExists_DataBase = False
End Function

<强>应用

Function TestFunction_Application()
  Dim ac As New Access.Application

  ac.OpenCurrentDatabase "the db path"

  MsgBox TdefExists_Application(ac, "the table name")

  ac.Quit
  Set ac = Nothing

End Function

Function TdefExists_Application(ac As Access.Application, strTableName As String) As Boolean
  'check to see if table exists
  On Error GoTo ErrHandler
  Dim strBS As String

  strBS = ac.CurrentDb.TableDefs(strTableName).Name
  TdefExists_Application = True
  Exit Function
ErrHandler:
  TdefExists_Application = False
End Function

在当前数据库中:

Function TdefExists(strName As String) As Boolean
    'check to see if query exists
    On Error GoTo ErrHandler
    Dim strBS As String
    strBS = CurrentDb.TableDefs(strName).Name
    TdefExists = True
    Exit Function
  ErrHandler:
    TdefExists = False
End Function