【问题标题】:Saving changes to a multivalued ComboBox via AuditTrail通过 AuditTrail 将更改保存到多值组合框
【发布时间】:2016-05-15 11:03:40
【问题描述】:

我有一个使用多值字段的 Access 2010 数据库(Access 的内置方式可以在两个表之间建立 m:n 关系)。
为了跟踪对数据库的更改,每次更新相应的表单时,我都会使用 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

【问题讨论】:

  • 感谢@Andre 的更改。我不是本地人,我的访问权限是德语,所以我必须翻译所有内容^^

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


【解决方案1】:

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 在没有选择任何项目时将为 Null。并且尝试Join()Null 也会触发类型不匹配错误。

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • ComboBox 已经有一个内置的 .OldValue 属性,我认为它工作正常。我的问题是我不明白如何从 .Value 或 .OldValue 属性中获取“文本”值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多