【问题标题】:How to loop through all Tables in an MS Access DB如何遍历 MS Access DB 中的所有表
【发布时间】:2013-07-07 11:16:35
【问题描述】:

我需要读取 Access 2003 数据库中 100 多个表的属性并将这些详细信息(表名、字段名、类型和大小)写入文件以获取进一步的文档。

我在网络搜索中找不到任何关于读取字段属性的信息,只有字段值...

谁能告诉我我必须声明哪些记录集变量(和语法)才能遍历数据库中的所有表并从每个表中提取字段名称、类型和大小?我会将结果写入文本文件,但我想我可以处理! :)

在我能解决这个问题之前,我处于停顿状态。我花了一天时间手动记录两张表。有些表有超过 100 个字段。

【问题讨论】:

    标签: ms-access vba


    【解决方案1】:

    您将不得不稍微调整一下,它旨在将表从一个数据库复制到另一个数据库,但它应该是一个很好的起点。

        ' Database.
        Dim dbRep As DAO.Database
        Dim dbNew As DAO.Database
    
        ' For copying tables and indexes.
        Dim tblRep As DAO.TableDef
        Dim tblNew As DAO.TableDef
        Dim fldRep As DAO.Field
        Dim fldNew As DAO.Field
        Dim idxRep As DAO.Index
        Dim idxNew As DAO.Index
    
        ' For copying data.
        Dim rstRep As DAO.Recordset
        Dim rstNew As DAO.Recordset
        Dim rec1 As DAO.Recordset
        Dim rec2 As Recordset
        Dim intC As Integer
    
        ' For copying table relationships.
        Dim relRep As DAO.Relation
        Dim relNew As DAO.Relation
    
        ' For copying queries.
        Dim qryRep As DAO.QueryDef
        Dim qryNew As DAO.QueryDef
    
        ' For copying startup options.
        Dim avarSUOpt
        Dim strSUOpt As String
        Dim varValue
        Dim varType
        Dim prpRep As DAO.Property
        Dim prpNew As DAO.Property
    
        ' For importing forms, reports, modules, and macros.
        Dim appNew As New Access.Application
        Dim doc As DAO.Document
    
        ' Open the database, not in exclusive mode.
        Set dbRep = OpenDatabase(Forms!CMDB_frmUpgrade.TxtDatabase, False)
    
    
        ' Open the new database
        Set dbNew = CurrentDb
    
        DoEvents
    
        ' Turn on the hourglass.
        DoCmd.Hourglass True
    
        '********************
        Debug.Print "Copy Tables"
        '********************
    If Forms!CMDB_frmUpgrade.CkTables = True Then
        Forms!CMDB_frmUpgrade.LstMessages.addItem "Copying Tables:"
    
        ' Loop through the collection of table definitions.
        For Each tblRep In dbRep.TableDefs
        Set rec1 = dbRep.OpenRecordset("SELECT MSysObjects.Name FROM MsysObjects WHERE ([Name] = '" & tblRep.Name & "') AND ((MSysObjects.Type)=4 or (MSysObjects.Type)=6)")
    
        If rec1.EOF Then
          XF = 0
        Else
          XF = 1
        End If
    
            ' Ignore system tables and CMDB tables.
            If InStr(1, tblRep.Name, "MSys", vbTextCompare) = 0 And _
                InStr(1, tblRep.Name, "CMDB", vbTextCompare) = 0 And _
                XF = 0 Then
    
                '***** Table definition
                ' Create a table definition with the same name.
                Set tblNew = dbNew.CreateTableDef(tblRep.Name)
                Forms!CMDB_frmUpgrade.LstMessages.addItem "--> " & tblRep.Name & ""
    
                ' Set properties.
                tblNew.ValidationRule = tblRep.ValidationRule
                tblNew.ValidationText = tblRep.ValidationText
    
                ' Loop through the collection of fields in the table.
                For Each fldRep In tblRep.Fields
    
                    ' Ignore replication-related fields:
                    ' Gen_XXX, s_ColLineage, s_Generation, s_GUID, s_Lineage
                    If InStr(1, fldRep.Name, "s_", vbTextCompare) = 0 And _
                        InStr(1, fldRep.Name, "Gen_", vbTextCompare) = 0 Then
    
                        '***** Field definition
                        Set fldNew = tblNew.CreateField(fldRep.Name, fldRep.Type, _
                            fldRep.Size)
    
                        ' Set properties.
                        On Error Resume Next
                        fldNew.Attributes = fldRep.Attributes
                        fldNew.AllowZeroLength = fldRep.AllowZeroLength
                        fldNew.DefaultValue = fldRep.DefaultValue
                        fldNew.Required = fldRep.Required
                        fldNew.Size = fldRep.Size
    
                        ' Append the field.
                        tblNew.Fields.Append fldNew
                        'On Error GoTo Err_NewShell
                    End If
                Next fldRep
    
                '***** Index definition
    
                ' Loop through the collection of indexes.
                For Each idxRep In tblRep.Indexes
    
                    ' Ignore replication-related indexes:
                    ' s_Generation, s_GUID
                    If InStr(1, idxRep.Name, "s_", vbTextCompare) = 0 Then
    
                        ' Ignore indices set as part of Relation Objects
                        If Not idxRep.Foreign Then
    
                            ' Create an index with the same name.
                            Set idxNew = tblNew.CreateIndex(idxRep.Name)
    
                            ' Set properties.
                            idxNew.Clustered = idxRep.Clustered
                            idxNew.IgnoreNulls = idxRep.IgnoreNulls
                            idxNew.Primary = idxRep.Primary
                            idxNew.Required = idxRep.Required
                            idxNew.Unique = idxRep.Unique
    
                            ' Loop through the collection of index fields.
                            For Each fldRep In idxRep.Fields
                                ' Create an index field with the same name.
                                Set fldNew = idxNew.CreateField(fldRep.Name)
                                ' Set properties.
                                fldNew.Attributes = fldRep.Attributes
                                ' Append the index field.
                                idxNew.Fields.Append fldNew
                            Next fldRep
    
                            ' Append the index to the table.
                            tblNew.Indexes.Append idxNew
                        End If
                    End If
                Next idxRep
    
                ' Append the table.
                dbNew.TableDefs.Append tblNew
            End If
        Next tblRep
    

    【讨论】:

    • 感谢你们俩。我可以看到我现在需要做什么。很棒的东西。
    【解决方案2】:

    具有这些选项的 Database Documenter 向导应该会以最少的努力为您提供所需的内容。

    如果该方法不令人满意,您可以使用自定义 VBA 代码来收集您想要的信息。您可以通过循环访问 DAO TableDefs 集合来检索数据库中表的名称。

    Dim db As DAO.Database
    Dim tdf As DAO.TableDef
    Set db = CurrentDb
    For Each tdf In db.TableDefs
        ' ignore system and temporary tables
        If Not (tdf.name Like "MSys*" Or tdf.name Like "~*") Then
            Debug.Print tdf.name
        End If
    Next
    Set tdf = Nothing
    Set db = Nothing
    

    要获得所需的字段详细信息,请使用 Allen Browne 的 TableInfo() function ... 替换文件写入语句来替换 Debug.Print 语句。请注意,该函数使用 2 个帮助函数,GetDescripFieldTypeName,这两个函数都包含在该链接页面中。

    这是来自TableInfo() 的即时窗口输出示例,用于我的数据库中的一个表 --- 我认为它包含您想要的字段信息。

    TableInfo "foo"
    FIELD NAME    FIELD TYPE    SIZE          DESCRIPTION
    ==========    ==========    ====          ===========
    id            AutoNumber     4            
    MyNumber      Long Integer   4            
    MyText        Text           255          
    bar           Long Integer   4            
    ==========    ==========    ====          ===========
    

    调整函数后,从上面示例中的 For Each tdf 循环调用它,并为每个 tdf.name 提供它:

    TableInfo tdf.name
    

    【讨论】:

      【解决方案3】:

      下面的sub会将所有表名、字段名、类型、必填、默认值导出到excel表中

      Sub TableDef()
       Dim def As TableDef
       Dim wb As Object
       Dim xL As Object
       Dim lngRow As Long
       Dim f As Field
       Set xL = CreateObject("Excel.Application")
       xL.Visible = True
       Set wb = xL.workbooks.Add
       lngRow = 2
       For Each def In CurrentDb.TableDefs
         For Each f In def.Fields
           With wb.sheets("Sheet1")
                 .Range("A" & lngRow).Value = def.Name
                 .Range("B" & lngRow).Value = f.Name
                 .Range("C" & lngRow).Value = f.Type
                 .Range("D" & lngRow).Value = f.Size
                 .Range("E" & lngRow).Value = f.Required
                 .Range("F" & lngRow).Value = f.DefaultValue
                  lngRow = lngRow + 1
          End With
         Next
       Next
      End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-07
        • 2020-12-02
        • 2011-03-21
        • 1970-01-01
        • 2015-12-10
        • 2018-11-03
        • 1970-01-01
        相关资源
        最近更新 更多