我在 Stack Overflow 页面中发现了这个(修改过的)函数,并一直试图让它工作而不放弃传递的对象(如果我严格在第一个例程它会起作用)。
是的,我知道有很多方法可以得到相同的答案(主要来自堆栈上的其他帖子),但是这里有一个通用概念,即将对象传递给我想掌握的函数--请暂时忘记该函数检查表是否存在。
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
只是想补充一点,我在技术上发布的最后一个函数将被视为部分柯里化(Currying)或无柯里化(Currying),具体取决于调用“Access.Application.CurrentData.AllTables”对函数范围的限制程度。作为“theDatabase”的替代品,仅将 Access.Application.CurrentDb.Name 创建的特定字符串替换到原始函数中...(theDatabse,...这才是真正的完全柯里化(Currying)。
无论如何,将对象传递给函数和库及其方法是本次讨论的主要焦点。当我解决 DAO 问题时,我应该对可能发生的情况有更好的感觉,然后我将相应地发布并标记最佳解决方案。
最佳答案
问题实际上并不在于将 Access.Application
对象传递给其他函数。相反,您创建 Access.Application
并稍后检查表是否存在,而无需在该 Access session 中打开数据库。在这种情况下,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 数据库之前,我没有包含任何检查它是否存在的规定。因此,如果您给它一个不存在的数据库路径,您将会收到错误。
DAO 引用问题:
DAO 3.6 是旧 DAO 系列的最后一个。它仅支持较旧的MDB类型数据库。当 Access 2007 引入 ACCDB 数据库类型时,引入了新的 DAO 库(Access 数据库引擎对象库,有时称为ACEDAO)。除了支持 ACCDB 数据库之外,ACEDAO 还可以支持较旧的 MDB 类型。
设置引用时,不要尝试同时选择两者。
这是我的项目引用的屏幕截图:
当我在“立即”窗口中检查我的项目引用时,请注意ACEDAO甚至被称为DAO。我还运行了 callFCN_CheckTblsExist 过程来演示它在没有 DAO 3.6 引用的情况下也能正常工作:
这一切都基于 Access 2010。您使用的是 Access 2013,因此您的 ACEDAO 版本号可能不同,但其他所有内容都应该相同。
关于ms-access - 将 Access.Application 对象传递给函数 : Dim, Set, Object 如何使其工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31395279/