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

时间:2016-02-05 12:48:05

标签: ms-access combobox access-vba ms-access-2010 audit-trail

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

现在,当我更改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

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

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

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

2 个答案:

答案 0 :(得分:2)

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, ",")

如果这似乎有用,请注意ctl.Value在没有选择任何项目时将为空。并且尝试Join() Null也会触发类型不匹配错误。

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

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

答案 1 :(得分:0)

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

修改您的代码,以便它以不同的方式检查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