Сохранение изменений в многозначном ComboBox через AuditTrail

У меня есть база данных Access 2010, использующая многозначное поле (встроенный способ доступа, чтобы иметь отношение 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

Как я могу получить фактический Value и OldValue из выпадающего списка, преобразованного в строку в VBA?

Я старался combobox.focus а потом combobox.TextЭто работает, но не помогает с OldValue проблема.

Как правильно использовать value а также oldvalue свойство комбобоксов? Официальная ссылка на объект VBA для комбинированных списков не помогает вообще. https://msdn.microsoft.com/en-us/library/office/ff821691.aspx

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

Когда 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) в вашей процедуре аудита.

Другие вопросы по тегам