我可以使用 Access VBA 来确定表是不是有数据宏吗?

Posted

技术标签:

【中文标题】我可以使用 Access VBA 来确定表是不是有数据宏吗?【英文标题】:Can I use Access VBA to determine if a table has a Data Macro?我可以使用 Access VBA 来确定表是否有数据宏吗? 【发布时间】:2015-07-31 21:57:36 【问题描述】:

有没有办法通过 VBA 确定 Access 表是否包含数据宏?我的大部分表都有数据宏,但如果遇到没有它的表,我的代码会失败。

我没有收到错误消息。相反,代码继续运行,就好像它处于无限循环中,但我必须强制 Access 退出才能逃脱。

具体来说,我正在尝试保存我的所有表格和数据宏,以便以后可以使用(未​​记录的)LoadFromText 函数重新创建它们。

我在下面的代码示例中用 ** BUG ** 突出显示了问题。

For Each td In db.TableDefs 
    If Left(td.Name, 4) <> "MSys" Then

        'Save the table as a text file.        
        DoCmd.TransferText acExportDelim, , td.Name, sExportLocation & "Table_" & td.Name & ".txt", True

        'Save the table's data macro as an XML file. 
        '** BUG **: If a table doesn't have a data macro, Access freezes/starts infinite loop.
        Application.SaveAsText acTableDataMacro, td.Name, sExportLocation & "Table_" & td.Name & "_DataMacro.xml"

    End If
Next td

我假设我想要某种嵌套的 If 语句,它首先检查表中是否存在数据宏。不过我不知道该怎么写。

感谢指出 SaveAsText 和 LoadFromText 函数 in another SO post 的人们。这些功能似乎有很大的潜力。

【问题讨论】:

如果我在没有 DataMacros 的表上执行 SaveAsText(),我会收到运行时错误“2950”,“保留错误”。代码 sn-p 显然不完整,因为它没有所有变量声明等。也许您的错误处理设置不正确/最佳。我建议添加一个显式的“On Error Goto 0”并从从立即窗口执行的单个子过程中运行代码。 值得注意的是,我正在使用带有 VBA 7.1 和 MS Office Pro 2016 的 MS Office Pro Plus 2013 运行 Access。 【参考方案1】:

您可以使用简单查询来指示表是否具有数据宏:

SELECT [Name] FROM MSysObjects WHERE Not IsNull(LvExtra) and Type =1

此宏可应用于问题中的 VBA 代码,如下所示:

For Each td In db.TableDefs
    If Left(td.Name, 4) <> "MSys" Then

        'Save the table as a text file.
        DoCmd.TransferText acExportDelim, , td.Name, sExportLocation & _
            "Table_" & td.Name & ".txt", True

        'Define a recordset to determine if the table has a data macro.
        sql = "SELECT [Name] FROM MSysObjects WHERE Not IsNull(LvExtra) and " & _
            "Type = 1 and [Name] = '" & td.Name & "'"
        Set rst = db.OpenRecordset(sql, dbOpenSnapshot)

        'If the table has a data macro, save the data macro as an XML file.
        If rst.RecordCount <> 0 Then
            Application.SaveAsText acTableDataMacro, td.Name, sExportLocation & _
                "Table_" & td.Name & "_DataMacro.xml"
        End If

        'Close the recordset and clear its variable.
        If Not rst Is Nothing Then
            rst.Close
            Set rst = Nothing
        End If

    End If
Next td

感谢引用 UtterAccess 帖子的 a post on UtterAccess 和 @Scotch's answer to a question on SO。

【讨论】:

我应该添加免责声明,即我找不到任何官方或非官方文档来解释 LvExtra 字段包含的内容。在 Access 中,该字段仅显示“长二进制数据”。【参考方案2】:

要查看数据库是否包含宏,您可以使用 DAO 中记录的方法。这是来自https://msdn.microsoft.com/en-us/library/office/ff191764.aspx的修改示例:

Sub ContainerObjectX()

 Dim dbsNorthwind As Database
 Dim ctrLoop As Container
 Dim prpLoop As Property
 Dim docItem As Document

 '  Set dbsNorthwind = OpenDatabase("Northwind.mdb")
 Set dbsNorthwind = CurrentDb

 With dbsNorthwind

 ' Enumerate Containers collection.
 For Each ctrLoop In .Containers
    Debug.Print "Properties of " & ctrLoop.Name _
    & " container"

    ' Enumerate Properties collection of each
    ' Container object.
    For Each prpLoop In ctrLoop.Properties
       Debug.Print " " & prpLoop.Name _
           & " = "; prpLoop
    Next prpLoop

    For Each docItem In ctrLoop.Documents
       Debug.Print " docItem.Name = "; docItem.Name
    Next docItem
 Next ctrLoop

 .Close
 End With

End Sub

所以你只需要检查“脚本”容器下的文档。

我原来的答案: 我认为您可以使用 ExportXML 和 ImportXML 功能更强大,并且能够导出和导入所有访问对象。 示例:

ExportXML acExportTable, "tblMain", CM_GetDBPath() & "AccessFunc_Tbl.xml" _  
, CM_GetDBPath() & "AccessFunc_TblShema.xml", CM_GetDBPath() & "AccessFunc_Tbl.xsl" _  
, "Images", , acEmbedSchema

....

ImportXML CM_GetDBPath() & "AccessFunc_Tbl.xml", acAppendData 

完整示例在这里:http://5codelines.net/wp-content/uploads/xml_1_sampe.rar

您也可以使用 ADODB 库。

Public Function EportTblToXml(ByVal imTblFrom As String _  
                             , ByVal imFileTo As String)  
    Dim rstData As ADODB.Recordset  
    Dim cnn As ADODB.Connection                 

    Set cnn = CurrentProject.Connection  
    Set rstData = New ADODB.Recordset       

    rstData.Open "SELECT * FROM " & imTblFrom, cnn _  
                     , adOpenKeyset, adLockOptimistic  
    Call SaveRstToXml(rstData, imFileTo)  
    rstData.Close  
End Function  

Public Function LoadXmlToRst(ByVal stFileName As String) As ADODB.Recordset  
    Dim rst As ADODB.Recordset  
    Set rst = New ADODB.Recordset       

    rst.Open stFileName
    Set LoadXmlToRst = rst  
End Function  

【讨论】:

你的帖子很有趣,但我不认为它回答了我的问题。你能解释一下ExportXMLImportXML 将如何处理一个表的数据宏吗?例如,如果我将表导出或导入为 XML,我应该能够包含表的数据宏吗?如果是这样,怎么做?我对其进行了试验,但无法包含该(元)数据。 对不起,我混淆了你的问题。我认为您需要提取数据。 在我的原始答案中添加了一些注释。我希望它会有所帮助。 您只能使用 CurrentDB.Containers("Scripts").Documents 集合查看常规宏。同样,CurrentProject.AllMacros 也将只显示常规宏。这些都不显示数据宏。

以上是关于我可以使用 Access VBA 来确定表是不是有数据宏吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 VBA 在 Access 中重新查询子表

Access 2010中使用VBA创建动态表

比较 VBA Access 中的表

带有空格和范围的 MS Access VBA acImport 工作表名称

MS Access VBA 修改 Excel 工作表而不写入 Drive

最后插入行的自动编号值 - MS Access / VBA