Для каждого не работает должным образом в коде VBA - PullRequest
1 голос
/ 24 декабря 2008

Что ж, я почти закончил завершать аудиторскую часть моего приложения, которую я обсуждал здесь . Я делаю это, перебирая все текстовые поля, выпадающие списки и флажки и сохраняя их значения в событии form_load. Затем я делаю то же самое в событии form_afterUpdate и сравниваю их. Если есть разница, я регистрирую это, если нет, я продолжаю. Вот код:

Dim strValues(1 To 32) As String

Private Sub Form_AfterUpdate()
    Dim strCurrentValue, strSQL As String
    Dim intCurrentField As Integer
    intCurrentField = 1

    For Each C In Forms!frmVendorsManageVendors.Controls
        Select Case C.ControlType
            Case acTextBox, acComboBox, acCheckBox
                //Doing this because I don't want a NULL as it won't concatenate in the SQL query and don't want 0 or -1 for the boolean fields
                strCurrentValue = IIf(IsNull(C), "", IIf(C = vbTrue Or C = vbFalse, IIf(C = vbTrue, "Yes", "No"), C))

                If strValues(intCurrentField) <> strCurrentValue Then
                    strSQL = "INSERT INTO changesTable (change_time,user_affected,field_affected,old_value,new_value) VALUES (NOW()," & [id] & ",'" & C.ControlSource & "','" & strValues(intCurrentField) & "','" & strCurrentValue & "')"

                    DoCmd.SetWarnings False
                    DoCmd.RunSQL strSQL
                    //InputBox "", "", strSQL
                    strSQL = "WEEEE"
                    DoCmd.SetWarnings True

                    strValues(intCurrentField) = strCurrentValue
                End If

                intCurrentField = intCurrentField + 1
        End Select
    Next
End Sub

Private Sub Form_Open(Cancel As Integer)
    Call btnLock_Click

    Dim intCurrentField As Integer
    intCurrentField = 1

    For Each C In Forms!frmVendorsManageVendors.Controls
        Select Case C.ControlType
            Case acTextBox, acComboBox, acCheckBox
                //Doing this because I don't want a NULL as it won't concatenate in the SQL query and don't want 0 or -1 for the boolean fields
                strValues(intCurrentField) = IIf(IsNull(C), "", IIf(C = vbTrue Or C = vbFalse, IIf(C = vbTrue, "Yes", "No"), C))
                intCurrentField = intCurrentField + 1
        End Select
    Next
End Sub

Как вы можете видеть, есть закомментированная строка, в которую я вставляю таблицу изменений, которая помещает запрос в поле ввода, чтобы я мог скопировать / вставить его и посмотреть на него. Когда я раскомментирую эту строку, все в порядке. Если это закомментировано, оно генерирует первое точное изменение, но затем не изменит его для других элементов управления. Поэтому, если я изменю field1 и field2, он вставит изменение поля 1 дважды.

Это довольно запутанно, и я не знаю, почему это происходит.

Также я знаю, что я использую неправильный синтаксис комментариев, но если я использую правильный синтаксис, то SO "code color" er не будет отображаться правильно.

Ответы [ 3 ]

1 голос
/ 26 декабря 2008

Я не уверен, что у меня есть полный ответ, но пара замечаний.

Вы можете устранить некоторые строки кода, используя CurrentDB.Execute strSQL. Это устраняет необходимость в вызовах SetWarnings. Он работает непосредственно с базой данных, не взаимодействуя с обычными интерфейсными механизмами.

В целях отладки может быть лучше использовать Debug.Print для вывода строки SQL в окно отладки. Он избегает вовлечения пользовательского интерфейса и по-прежнему помещает SQL, где вы можете скопировать его в буфер обмена, если хотите захватить его и работать с ним.

Я думаю, что есть небольшая вероятность того, что вызов метода DoCmd для выполнения вашего SQL, даже с вызовами SetWarnnigs, может изменить что-то в интерфейсе, чтобы отвлечь внимание от формы, как предложил Шахкалпеш. Я делал подобные вещи и не видел проблемы, с которой вы столкнулись, поэтому мой единственный совет по самой проблеме - поступать так, как я, и переключаться на CurrentDB.Execute и исключать обращения к DoCmd внутри цикла.

Просто любопытно - почему вы использовали массив для предыдущих значений, а не свойство OldValue для элементов управления?

0 голосов
/ 30 января 2009

Вы пытались сделать это с помощью оператора execute (что-то вроде этого)?

Dim db As DAO.Database    'Inside the transaction.
Set db = CurrentDB
strSQL = "INSERT INTO changesTable (change_time, user_affected, " & _ 
            "field_affected, old_value, new_value) VALUES (NOW()," & [id] & _
            ",'" & C.ControlSource & "','" & strValues(intCurrentField) & _
            "','" & strCurrentValue & "')"
db.Execute strSql
0 голосов
/ 24 декабря 2008

Я предполагаю, что AfterUpdate может быть неподходящим событием для использования.

Кроме того, установка поля ввода может привести к тому, что существующий элемент управления потеряет фокус (что заставляет его работать правильно).

Я бы посоветовал проверить, что каждый из ваших элементов управления запущен, поместив msgbox C.name в цикл после выбора.

...