我有一个使用多值字段的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中的字符串中获取实际Value
和OldValue
?
我尝试combobox.focus
然后combobox.Text
这有效,但对OldValue
问题没有帮助。
如何正确使用组合框的value
和oldvalue
属性?组合框的官方VBA对象参考根本没有帮助。
https://msdn.microsoft.com/en-us/library/office/ff821691.aspx
答案 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