如何检查 VBA 模块何时被修改?

DHW*_*DHW 5 ms-access vba

我写了一个版本控制模块。每当我或其他维护者之一登录时,AutoExec 宏都会启动它。它会查找自上次更新以来已创建或修改的数据库对象,然后向版本表添加一个条目,然后打开该表(过滤为最后一条记录),这样我就可以输入我所执行的更改的摘要。

它对于表、查询、表单、宏等非常有效,但我无法让它在模块中正常工作。

我发现两个不同的属性表明了上次修改日期......

CurrentDB.Containers("Modules").Documents("MyModule").Properties("LastUpdated").Value
CurrentProject.AllModules("MyModule").DateModified
Run Code Online (Sandbox Code Playgroud)

第一个 (CurrentDB) 始终将“LastUpdated”显示为创建日期,除非您修改模块的描述或界面中的某些内容。这告诉我这个属性纯粹是针对容器对象的 - 而不是其中的内容。

第二个效果要好得多。它准确地显示了我修改和编译/保存模块的日期。唯一的问题是,当您保存或编译模块时,它会再次保存/编译所有模块,因此将 DateModified 字段全面设置为相同的日期。这有点违背了在各个模块上拥有 DateModified 属性的目的,不是吗?

所以我的下一步行动将会更加激烈。我想我需要维护所有模块的列表,并使用 VBA 扩展计算每个模块中的代码行数。然后,如果代码行与列表记录的不同 - 那么我知道该模块已被修改 - 我只是不知道什么时候,除了“自从我上次检查以来”

有人有更好的方法吗?我宁愿不执行下一步操作,因为我可以看到它明显影响数据库性能(以不好的方式)

Bla*_*awk 4

这是一个更简单的建议:

  1. 计算每个模块的 MD5 哈希值。
  2. 将其存储在版本表中。
  3. 在 AutoExec 期间重新计算每个模块的版本,并将其与版本表中的版本进行比较。如果不同,您可以假设它已被更改(虽然 MD5 不利于安全,但它对于完整性而言仍然可靠)。

要使用 VBE 扩展性从模块获取文本,您可以执行以下操作

Dim oMod As CodeModule
Dim strMod As String
Set oMod = VBE.ActiveVBProject.VBComponents(1).CodeModule
strMod = oMod.Lines(1, oMod.CountOfLines)
Run Code Online (Sandbox Code Playgroud)

然后您可以使用此答案中修改后的 MD5 哈希函数,如下所示,您可以将每个模块的哈希值存储起来,然后在 AutoExec 中进行比较。

Public Function StringToMD5Hex(s As String) As String
    Dim enc
    Dim bytes() As Byte
    Dim outstr As String
    Dim pos As Integer
    Set enc = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
    'Convert the string to a byte array and hash it
    bytes = StrConv(s, vbFromUnicode)
    bytes = enc.ComputeHash_2((bytes))
    'Convert the byte array to a hex string
    For pos = 0 To UBound(bytes)
        outstr = outstr & LCase(Right("0" & Hex(bytes(pos)), 2))
    Next
    StringToMD5Hex = outstr
    Set enc = Nothing
End Function
Run Code Online (Sandbox Code Playgroud)