【问题标题】:Get version of MS access database in VBA在 VBA 中获取 MS 访问数据库的版本
【发布时间】:2021-03-03 17:43:03
【问题描述】:

我在 Excel 365 > Visual Basic 编辑器中使用以下代码来尝试确定用于创建旧数据库的 MS Access 版本。该代码适用于我作为测试创建的较新的.accdb 数据库。据我所知,旧数据库最初是在 Access 97 中编写/设计的,但我想确定一下。

Public Sub GetAccessFormat()
    ' Attempt to determine the format of an Access database
    ' Note: Can Access 16.0 (Office 365) read databases from Office 2013 and earlier?
    On Error GoTo Error_NotAccessDatabase
    Dim fileName As String
    'fileName = "C:\Tmp\old.mdb"  ' Fails
    fileName = "C:\Tmp\new.accdb" ' Works
    
    If IsEmpty(Dir(fileName)) Then
        MsgBox "Could not find: " & fileName
        Exit Sub
    End If
    
    ' Open the database
    Dim objAccess As Object
    Set objAccess = CreateObject("Access.Application") ' Is this the problem?
    objAccess.OpenCurrentDatabase fileName
    objAccess.Visible = False
    
    ' Get the file format
    Dim fileFormat As Integer
    fileFormat = objAccess.CurrentProject.FileFormat ' Gets here and fails for .mdb (returns "12" for the .accdb)
    Dim strAccessFormat As String
    strAccessFormat = "Your database is: "
    
    Select Case fileFormat
        Case 2
            strAccessFormat = (strAccessFormat & "Microsoft Access 2")
        Case 7
            strAccessFormat = (strAccessFormat & "Microsoft Access 95")
        Case 8
            strAccessFormat = (strAccessFormat & "Microsoft Access 97")
        Case 9
            strAccessFormat = (strAccessFormat & "Microsoft Access 2000")
        Case 10
            strAccessFormat = (strAccessFormat & "Microsoft Access 2002")
        Case 11
            strAccessFormat = (strAccessFormat & "Microsoft Access 2003")
        Case 12
            strAccessFormat = (strAccessFormat & "Microsoft Access 2007")
        Case 14
            strAccessFormat = (strAccessFormat & "Microsoft Access 2010")
        Case 15
            strAccessFormat = (strAccessFormat & "Microsoft Access 2013")
        Case 16
            strAccessFormat = (strAccessFormat & "Microsoft Access 2016/9")
        Case Else
            strAccessFormat = "Unknown Access file format"
    End Select
    
    ' Close database and display the format information
    objAccess.CloseCurrentDatabase
    strAccessFormat = (strAccessFormat + " (" & fileFormat & ".0)")
    MsgBox strAccessFormat
    Exit Sub

Error_NotAccessDatabase:
    ' Unable to open the database (not Access or not supported by this version of Office?)
    MsgBox "Unable to open as Access database: " & strFile & ", Error: " & Err.Description
    Exit Sub
End Sub

错误文本是“您输入的表达式引用了一个已关闭或不存在的对象。” (数据库确实存在,没有在另一个应用程序中打开并且数据库上没有锁)

我们安装了 Office 365(带有 Access 16.0),所以我认为问题出在 Set objAccess = CreateObject("Access.Application"),因为我 PC 上的“访问应用程序”将无法读取旧格式的访问数据库。

这是正确的吗?是否有一种解决方法来确定旧 Access 数据库的文件格式?

【问题讨论】:

  • 您不需要像主机那样使用后期绑定声明。它已经被你使用它的性质加载了。删除 objAccess 并简单地替换为 Application
  • 请注意,Access_2013 及更高版本绝对拒绝从 Access_97 及更早版本打开 .mdb 文件。
  • @HackSlash:不确定我是否遵循。 ApplicationActiveCell 这样的成员,但没有 CurrentProjectFileFormat 成员或属性。
  • @AlainD,请参阅我的答案中的测试代码。如果您看到ActiveCell,那么听起来您正在使用 Excel。您的标签上写着ms-access,所以我假设您使用 Access 作为主机来运行 VBA。如果不是预期的,请在您的问题中说明您使用的 VBA 主机。
  • @HackSlash:是的 Excel...除了 Microsoft Office 产品之外,还有其他 VBA 主机吗?我确实澄清了我使用的是 Office 365,问题中是否缺少某些内容?

标签: vba ms-access


【解决方案1】:

您还可以“窥视”文件的第 21 个字节并从中确定其文件类型:

Function GetAccessFileType(filePath As String) As String
    Dim strm As New ADODB.Stream
    strm.Type = adTypeBinary
    strm.Open
    strm.LoadFromFile filePath
    strm.Read 20
    Dim bytes As Variant
    bytes = strm.Read(1)
    Dim fileTypeNumber As Integer
    fileTypeNumber = CInt(bytes(0))
    strm.Close
    Set strm = Nothing
    Dim fileTypeString As String
    Select Case fileTypeNumber
        Case 0:
            fileTypeString = "Access 97 or older"
        Case 1:
            fileTypeString = "Access 2000/2003"
        Case 2:
            fileTypeString = "Access 2007"
        Case 3:
            fileTypeString = "Access 2010"
        Case 5:
            fileTypeString = "Access 2016 with BIGINT support (Type 5)"
        Case Else:
            fileTypeString = "Unknown (" & fileTypeNumber & ")"
    End Select
    GetAccessFileType = fileTypeString
End Function

【讨论】:

  • 这个答案更好,因为它不依赖于 Access 能够打开文件。
  • 这行得通!除了 ADODB 在我的 Excel 版本中的 VBA 中未被识别。所以我用Binary Access Read打开文件,并将前21个字节读入定义为Dim buffer() As Byte的类型。现在buffer(20) 包含数据文件类型号。
【解决方案2】:

您通常不想使用完整的Access.Application 对象来测试版本,尝试只使用DAO.DbEngine 一个:

    ' Open the database
    Dim dbe As Object
    If fileName Like "*.mdb" Then
        Set dbe = CreateObject("DAO.DbEngine.36") 
        'Old JET engine, on 32-bits likely the MDAC version that still supports Access 2.0
    Else
        Set dbe = CreateObject("DAO.DbEngine.120")
        'ACE engine
    End If
    Dim db As Object
    Set db = dbe.OpenDatabase(fileName)
    
    ' Get the file format
    Dim fileFormat As String
    fileFormat = db.Version 'Decode: https://docs.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/database-version-property-dao

请注意,CurrentProject.FileFormatDatabase.Version 都不会超过 12.0。

我们也可以尝试得到更准确的版本:

fileFormat = db.Properties!Version 'Decode = ???

但是,对于这个版本,我没有准备好解码器。对于没有最近使用的字段(没有扩展 bigint/datetime)创建的 accdb,它返回“12.0”,这与 2010 年的功能是最近使用的一致。

但是,如果我添加一个日期时间扩展字段,它会跳转到“32.0”,这更难解码,尤其是从 2016 年开始,数据库功能与主要的 Office 版本不对应(2016 年初的版本不支持bigint,2016 年末的版本)。

【讨论】:

  • 如何使用 64 位 Excel 在 VBA 中使用 DAO 3.6?在我的 VBA 项目中添加对 Microsoft DAO 3.6 Object Library 的引用导致“加载 DLL 时出错”。我发现 COM 对象注册到 %CommonProgramFiles%\Microsoft Shared\DAO\dao360.dll 而不是 %CommonProgramFiles(x86)%。我手动注册 DLL 的努力导致注册表没有变化,所以我将dao360.dll 改为C:\Program Files\Common Files\microsoft shared\DAO。现在我可以添加对Microsoft DAO 3.6 Object Library 的引用,但“DAO.DbEngine.36”仍然“无法识别”。
  • 对于初学者,我会使用后期绑定。如果您仅限于 64 位 Excel,那么 use a COM surrogate。将 32 位 DLL 移动到不同的文件夹并不会突然使其与 64 位程序一起使用,您需要代理进行翻译。
  • 哇,刚刚在dao360.dll(Windows 10、Excel 365)上尝试了 COM 代理,它可以工作!
【解决方案3】:

根据微软:

将 Access 97 数据库转换为 .accdb 格式

从 Access 2013 开始,不再可以直接转换 将 Access 97 数据库 (.mdb) 转换为 .accdb 文件格式。然而,你 可以在以前版本的 Access 中打开 Access 97 数据库,并且 然后以 Access 2013 可以打开的格式保存数据库。为了 例如,这里是如何使用 Access 2003 打开 Access 97 数据库, 然后将其转换为 Access 2013 可以打开的格式:

  1. 在 Access 2003 中打开 Access 97 数据库。

  2. 单击工具 > 数据库实用程序 > 转换数据库 > 到 Access 2002-2003文件格式。

  3. 输入数据库名称并点击保存。

  4. 关闭 Access 2003 并打开 Access 2013。

  5. 打开数据库并单击文件 > 另存为 > 访问数据库 (.accdb) > 另存为 > 保存。

您也可以使用 Access 2007 或 Access 2010 来转换 Access 97 数据库为 .accdb 格式。当您在中打开 Access 97 数据库时 这两种产品中的任何一种,都会出现数据库增强向导 帮助将数据库转换为 .accdb 格式。

来源: https://support.microsoft.com/en-us/office/convert-a-database-to-the-accdb-file-format-098ddd31-5f84-4e89-8f44-db0cf7c11acd#__convert_an_access

替代解决方案:

如果您没有旧版本的 Access,并且想要提取数据,您可以使用任何现代 Excel 版本,使用“数据”选项卡上的导入功能来执行此操作。将数据保存到 Excel 后,您可以将其从 Excel 重新导入 Access。

测试代码:

话虽如此,这里是您的代码的测试版本,可与 Access 可以打开的任何数据库一起使用:

Public Sub GetAccessFormat()
    ' Attempt to determine the format of an Access database
    On Error GoTo Error_NotAccessDatabase
    Dim fileName As String
    'fileName = "C:\Tmp\old.mdb"  ' Fails
    fileName = "C:\Tmp\new.accdb" ' Works
    
    If IsEmpty(Dir(fileName)) Then
        MsgBox "Could not find: " & fileName
        Exit Sub
    End If
    
    ' Open the database
    Application.OpenCurrentDatabase fileName
    Application.Visible = False
    
    ' Get the file format
    Dim strAccessFormat As String
    strAccessFormat = "Your database is: "
    
    Select Case Application.CurrentProject.FileFormat
        Case acFileFormatAccess2
            strAccessFormat = (strAccessFormat & "Microsoft Access 2")
        Case acFileFormatAccess95
            strAccessFormat = (strAccessFormat & "Microsoft Access 95")
        Case acFileFormatAccess97
            strAccessFormat = (strAccessFormat & "Microsoft Access 97")
        Case acFileFormatAccess2000
            strAccessFormat = (strAccessFormat & "Microsoft Access 2000")
        Case acFileFormatAccess2002
            strAccessFormat = (strAccessFormat & "Microsoft Access 2002")
        Case 11
            strAccessFormat = (strAccessFormat & "Microsoft Access 2003")
        Case 12
            strAccessFormat = (strAccessFormat & "Microsoft Access 2007")
        Case 14
            strAccessFormat = (strAccessFormat & "Microsoft Access 2010")
        Case 15
            strAccessFormat = (strAccessFormat & "Microsoft Access 2013")
        Case 16
            strAccessFormat = (strAccessFormat & "Microsoft Access 2016/9")
        Case Else
            strAccessFormat = "Unknown Access file format"
    End Select
    
    ' Close database and display the format information
    strAccessFormat = (strAccessFormat + " (" & Application.CurrentProject.FileFormat & ".0)")
    MsgBox strAccessFormat
    
    Application.CloseCurrentDatabase
    Exit Sub

Error_NotAccessDatabase:
    ' Unable to open the database (not Access or not supported by this version of Office?)
    MsgBox "Unable to open as Access database: " & fileName & ", Error: " & Err.Description
    Exit Sub
End Sub

【讨论】:

  • 很好的答案...但不幸的是在 Excel 365 中失败。错误是 Object doesn't support this property or method。我的Application 对象没有OpenCurrentDatabase 方法...
  • ( cc: @AlainD ) - Access 2010 Runtime 似乎仍然可以下载。我曾尝试将 Access 97 数据库转换为更新的数据库,它似乎对我来说还可以。 (不幸的是,我不记得细节了。)
  • @AlainD,这是一个 Access 问题,所以我给了你一个 Access 答案。为什么要从 Excel 打开 Access?只需在 Access 中执行即可。
  • Access 365 (Access 16.0) 不会打开旧的 .mdf 文件...
  • @AlainD 对,所以使用 Excel 内置的数据导入功能。不需要 VBA。它会将数据导入到您的工作簿中。
猜你喜欢
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-15
  • 2010-11-10
相关资源
最近更新 更多