将 Access.Application 对象传递给函数:Dim、Set、Object 如何使其工作?
passing Access.Application object to a function: Dim, Set, Object how to make it work?
我在 Stack Overflow 页面中发现了这个(修改过的)函数,并且一直在尝试让它工作而不放弃传递的对象(如果我在第一个例程中严格处理 Access.Application
它将工作)。
是的,我知道有很多方法可以得到相同的答案(主要来自堆栈上的其他 post),但是这里有一个将对象传递给函数的通用概念我想掌握的--请暂时忘记函数检查table.
是否存在
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(新?)体操在辅助程序中。可能存在参考库问题(我是 运行 Access 2013)。
更新: 我不确定以下内容是否足够稳健,但这就是我之前在 post 中的意思,只是为了完整性而放在这里。顺便说一句,这不是拆分应用程序,所以也许这就是以下工作的原因。我很欣赏 HansUp 的 post,关于这个主题还不够多。不管怎样
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
只是想补充一点,我 post 编辑的最后一个函数在技术上会被认为是部分柯里化或没有柯里化,这取决于通过调用 "Access.Application.CurrentData.AllTables." 作为替代 "theDatabase",仅将 Access.Application.CurrentDb.Name 创建的特定字符串代入原始函数 ...(theDatabse, ... 是否是真正的全柯里化。
无论如何,将对象传递给函数和库及其方法是本次讨论的主要焦点。当我解决 DAO 问题时,我应该对可能发生的事情有更好的感觉,然后我将 post 并相应地标记最佳解决方案。
问题不在于将 Access.Application
对象传递给您的其他函数。相反,您创建 Access.Application
并稍后检查 table 是否存在,而无需在该 Access 会话中打开数据库。在那种情况下,theDatabase.CurrentData.AllTables.Count
应该触发错误
2467、"The expression you entered refers to an object that is closed or doesn't exist."
我修改了这两个程序并在 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 类型。
设置引用时,不要同时选择两者。
这是我的项目引用的截图:
当我在 Immediate window 中检查我的项目引用时,请注意 ACEDAO 甚至被称为 DAO .我还 运行 callFCN_CheckTblsExist 程序来演示它在没有 DAO 3.6 参考的情况下工作:
以上均基于 Access 2010。您使用的是 Access 2013,因此您的 ACEDAO 版本号可能不同,但其他所有内容都应该相同。
这里有几个解决方案以及一个更简单的方法来检查 table 是否存在:
Workspace/Database; (比使用应用程序快得多)
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
我在 Stack Overflow 页面中发现了这个(修改过的)函数,并且一直在尝试让它工作而不放弃传递的对象(如果我在第一个例程中严格处理 Access.Application
它将工作)。
是的,我知道有很多方法可以得到相同的答案(主要来自堆栈上的其他 post),但是这里有一个将对象传递给函数的通用概念我想掌握的--请暂时忘记函数检查table.
是否存在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(新?)体操在辅助程序中。可能存在参考库问题(我是 运行 Access 2013)。
更新: 我不确定以下内容是否足够稳健,但这就是我之前在 post 中的意思,只是为了完整性而放在这里。顺便说一句,这不是拆分应用程序,所以也许这就是以下工作的原因。我很欣赏 HansUp 的 post,关于这个主题还不够多。不管怎样
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
只是想补充一点,我 post 编辑的最后一个函数在技术上会被认为是部分柯里化或没有柯里化,这取决于通过调用 "Access.Application.CurrentData.AllTables." 作为替代 "theDatabase",仅将 Access.Application.CurrentDb.Name 创建的特定字符串代入原始函数 ...(theDatabse, ... 是否是真正的全柯里化。
无论如何,将对象传递给函数和库及其方法是本次讨论的主要焦点。当我解决 DAO 问题时,我应该对可能发生的事情有更好的感觉,然后我将 post 并相应地标记最佳解决方案。
问题不在于将 Access.Application
对象传递给您的其他函数。相反,您创建 Access.Application
并稍后检查 table 是否存在,而无需在该 Access 会话中打开数据库。在那种情况下,theDatabase.CurrentData.AllTables.Count
应该触发错误
2467、"The expression you entered refers to an object that is closed or doesn't exist."
我修改了这两个程序并在 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 类型。
设置引用时,不要同时选择两者。
这是我的项目引用的截图:
当我在 Immediate window 中检查我的项目引用时,请注意 ACEDAO 甚至被称为 DAO .我还 运行 callFCN_CheckTblsExist 程序来演示它在没有 DAO 3.6 参考的情况下工作:
以上均基于 Access 2010。您使用的是 Access 2013,因此您的 ACEDAO 版本号可能不同,但其他所有内容都应该相同。
这里有几个解决方案以及一个更简单的方法来检查 table 是否存在:
Workspace/Database; (比使用应用程序快得多)
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