通过 AuditTrail 保存对多值 ComboBox 的更改

Saving changes to a multivalued ComboBox via AuditTrail

我有一个使用多值字段的 Access 2010 数据库(Access 内置方式在两个 table 之间建立 m:n 关系)。
为了跟踪对数据库的更改,每次更新相应的表单时我都使用 AuditTrail VBA 过程,将所有更改保存到历史记录 table.

现在,当我更改 ComboBox 的值并且循环到达绑定到多值字段的 ComboBox 时,由于数据类型不兼容,该过程会引发错误:

    For Each ctl In Screen.ActiveForm.Controls
    If ctl.Tag = "History" Then
        If Nz(ctl.Value) <> Nz(ctl.OldValue) Then
            With rst
                .AddNew
                ![timestamp] = datTimeCheck
                ![UserName] = strUserID
                ![FormName] = Screen.ActiveForm.Name
                ![recordid] = Screen.ActiveForm.Controls(IDField).Value
                ![FieldName] = ctl.ControlSource
                ![beforeValue] = ctl.OldValue
                ![afterValue] = ctl.Value
                .Update
            End With
        End If
    End If
Next ctl

如何从组合框中获取实际的 ValueOldValue 并将其转换为 VBA 中的字符串?

我尝试了 combobox.focus 然后 combobox.Text 这有效,但对 OldValue 问题没有帮助。

如何正确使用组合框的valueoldvalue属性?组合框的官方 VBA 对象参考根本没有帮助。 https://msdn.microsoft.com/en-us/library/office/ff821691.aspx

这不是一个优雅的解决方案,只是一个快速而肮脏的解决方法:

修改您的代码,使其以不同方式检查 ComboBox1 和其他控件。 .Value.OldValue 基本上是一个变体数组。

Dim afterValue as variant
Dim beforeValue as Variant

For Each ctl In Screen.ActiveForm.Controls
    If ctl.Tag = "History" Then
        If Ctl.name = "ComboBox1" then
           err.clear
           on error resume next
           I=0
           afterValue = ""
           beforeValue = ""
           while err=0
               '
               ' Throws an error if 'out of range', i.e. after the last value
               '
               afterValue = afterValue + Nz(Cstr(ComboBox1.Value(I))) + ";"
               beforeValue = beforeValue + Nz(Cstr(ComboBox1.OldValue(I))) + ";"

           wend
        else
           afterValue = ctl.Value
           beforeValue = Nz(ctl.OldValue)
        endif
        If Nz(ctl.Value) <> a$ Then
           With rst
              .AddNew
              ![timestamp] = datTimeCheck
              ![UserName] = strUserID
              ![FormName] = Screen.ActiveForm.Name
              ![recordid] = Screen.ActiveForm.Controls(IDField).Value
              ![FieldName] = ctl.ControlSource
              ![beforeValue] = beforeValue
              ![afterValue] = afterValue
              .Update
           End With
        End If
    End If
Next ctl

ctl 引用一个多值组合框且至少选择了一项时,您的测试条件...

Nz(ctl.Value) <> Nz(ctl.OldValue)

...肯定会抛出类型不匹配的错误。在那种情况下,ctl.Value实际上是一个变体数组,Nz()无法应对。问题本质上和这个是一样的...

Debug.Print Nz(Array(1,2,3)) '<- type mismatch error

也许您更愿意获取一串串联的组合选择...

Debug.Print Join(ctl.Value, ",")

如果这看起来有用,请注意当 none 项被选中时 ctl.Value 将为空。并且尝试 Join() Null 也会触发类型不匹配错误。

请注意,这些问题也适用于 ctl.OldValue

但可能还有另一个并发症。根据我的测试,我怀疑 OldValue 对于多值组合框是否可靠。如果您也发现是这种情况,请使用表单的当前事件将组合的初始选择存储在表单级变量中,并在您的审计过程中引用该变量(而不是 OldValue)。