muneermohd9690 Ответов: 1

Как регистрировать изменения в моей базе данных access с помощью VBA?


У меня есть база данных доступа для сотрудников, и некоторые пользователи с уровня менеджера имеют доступ к этой базе данных. Я хочу регистрировать любые изменения (добавлять новые,редактировать,удалять) в базу данных с помощью кода vba.пользователи будут использовать формы для внесения изменений. Я пробовал использовать приведенный ниже код,но проблема в том, что приведенный ниже код работает только для автономной формы. Мои формы содержат подформы и навигационные формы.

Что я уже пробовал:

Option Compare Database

Public Function auditchanges(recordid As String, useraction As String)
On Error GoTo auditerror
Dim DB As Database
Dim rst As Recordset
Dim clt As Control

Set DB = CurrentDb
Set rst = DB.OpenRecordset("select * from audittrail", adOpenDynamic)
userlogin = getuserlogon()
Select Case useraction
    Case "new"
        With rst
            .AddNew
            ![DateTime] = Now()
            ![username] = userlogin
            ![FormName] = Screen.ActiveForm.Name
            '![FormName] = Screen.ActiveForm.ActiveControl.Name
            ![Action] = useraction
            ![recordid] = Screen.ActiveForm.Controls(recordid).Value
            .Update
        End With
        
    Case "delete"
        With rst
            .AddNew
            ![DateTime] = Now()
            ![username] = userlogin
            ![FormName] = Screen.ActiveForm.Name
            '![FormName] = Screen.ActiveForm.ActiveControl.Name
            ![Action] = useraction
            ![recordid] = Screen.ActiveForm.Controls(recordid).Value
            .Update
        End With
        
    Case "edit"
         'For Each clt In Screen.ActiveForm.Controls
         For Each clt In Screen.ActiveForm.ActiveControl.Form
            If (clt.ControlType = acTextBox Or clt.ControlType = acComboBox) Then
                If Nz(clt.Value) <> Nz(clt.OldValue) Then
                    With rst
                        .AddNew
                        ![DateTime] = Now()
                        ![username] = userlogin
                        '![FormName] = Screen.ActiveForm.Name
                        ![FormName] = Screen.ActiveForm.ActiveControl.Form.Name
                        ![Action] = useraction
                        '![recordid] = Screen.ActiveForm.Controls(recordid).Value
                        '![recordid] = Screen.ActiveForm.ActiveControl.Form(recordid).Value
                        ![recordid] = Screen.ActiveForm.ActiveControl.Form(recordid).Value
                        ![FieldName] = clt.ControlSource
                        ![OldValue] = clt.OldValue
                        ![NewValue] = clt.Value
                        .Update
                    End With
                End If
             End If
        Next clt
        
End Select
rst.Close
DB.Close
Set rst = Nothing
Set DB = Nothing
auditerror:
    'MsgBox Err.Number & ":" & Err.Description, vbCritical, "Error"
    Exit Function
    
End Function

CHill60

Почему вы не можете вызвать функцию из подформ?

muneermohd9690

на самом деле я новичок в vb.это небольшой проект, над которым я работаю после просмотра стольких видео на youtube.поэтому я не знаю, можно ли вызвать функцию из подформы, которую я пытаюсь проверить.при необходимости я могу поделиться базой данных.

CHill60

Вы не можете поделиться базой данных там, где я могу получить к ней доступ с работы.
Кстати, небольшая поправка - это не VB, а VBA. Похоже, но все же совсем другое дело. Кроме того, видео на YouTube, если они не представлены в виде сводного курса, не являются хорошим способом изучения языка.

Откуда вы вызываете эту функцию в данный момент? Предположительно, ваши подформы имеют кнопки "ОК", чтобы указать, что вы хотите зафиксировать изменения?

muneermohd9690

https://www.dropbox.com/s/kaw7j17bheurs2x/empsystem_backup_270920201111111.accdb?dl=0

you can access the database using the above link.this was created on access 2019.i am calling the function from the subform where i need to do the auditing.yes i do have a save and delete button on the form.i need to audit any changes when save or delete pressed,which works actually when the form is opened as a a standalone form.but once i publish it to users they will only be able to access it using navigation forms which will contain the form as a sub form.adding a new record is on another form.later on i need to call the same function on this adding new record form as well.you can start from loginscreen form once you download the database.the username would be khalifa and password 1234.

CHill60

Нет. Я не могу получить доступ к базе данных по этой ссылке. Как я уже сказал, "Вы не можете поделиться базой данных в любом месте, где я могу получить к ней доступ с работы."
Просто поместите вызов функции аудита в код для кнопок сохранить, удалить, после того как вы сделали сохранение или удаление

Gerry Schmitz

Если бы у вас был общий "уровень доступа к данным" (DAL), вы бы не беспокоились о формах против подформ против консоли и т. д. DAL будет выполнять операции с БД и ведение журнала, учитывая объект "отправитель".

muneermohd9690

это база данных access с некоторыми небольшими кодами vba для удовлетворения функциональности управления записями сотрудников небольшого офиса.

1 Ответов

Рейтинг:
11

muneermohd9690

спасибо вам всем за все ваши предложения. Я пришел к решению о том, как это сделать .вы создадите глобальный модуль, назовете его auditchanges и вставите приведенный ниже код

Option Compare Database
Option Explicit

Sub AuditChangesSub(recordid As String, UserAction As String)
On Error GoTo AuditChangesSub_Err
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim ctl As Control
Dim userlogin As String
Set cnn = CurrentProject.Connection
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM audittrail", cnn, adOpenDynamic, adLockOptimistic
userlogin = getuserlogon()
Select Case UserAction
    Case "new"
        With rst
            .AddNew
            ![DateTime] = Now()
            ![UserName] = userlogin
            
            ![FormName] = Screen.ActiveControl.Parent.Form.Name
            ![Action] = UserAction
            ![recordid] = Screen.ActiveControl.Parent.Form(recordid).Value
            .Update
        End With
        
    Case "delete"
        With rst
            .AddNew
            ![DateTime] = Now()
            ![UserName] = userlogin
            
            ![FormName] = Screen.ActiveControl.Parent.Form.Name
            ![Action] = UserAction
            ![recordid] = Screen.ActiveControl.Parent.Form(recordid).Value
            .Update
        End With
        
    Case "edit"
         For Each ctl In Screen.ActiveControl.Parent.Controls
            If ctl.Tag = "Audit" Then
                If (ctl.ControlType = acTextBox Or ctl.ControlType = acComboBox) Then
                    If Nz(ctl.Value) <> Nz(ctl.OldValue) Then
                        With rst
                            .AddNew
                            ![DateTime] = Now()
                            ![UserName] = userlogin
                            ![FormName] = Screen.ActiveControl.Parent.Form.Name
                        
                            ![Action] = UserAction
                            ![recordid] = Screen.ActiveControl.Parent.Form(recordid).Value
                        
                            ![FieldName] = ctl.ControlSource
                            ![OldValue] = ctl.OldValue
                            ![NewValue] = ctl.Value
                            .Update
                        End With
                    End If
                End If
            End If
        Next ctl
    Case Else
            With rst
                .AddNew
                ![DateTime] = Now()
                ![UserName] = userlogin
                ![FormName] = Screen.ActiveControl.Parent.Form.Name
                ![Action] = UserAction
                ![recordid] = Screen.ActiveControl.Parent.Form(recordid).Value
                .Update
            End With
        
End Select
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
AuditChangesSub_Err:
    'MsgBox Err.Number & ":" & Err.Description, vbCritical, "Error"
    Exit Sub
    
End Sub

on the form which you want to audit the changes make sure you use the tag "Audit" on all the text boxes and combo boxes .and in the expression builder you will call the global function as below based on where you want to trigger the function,like for me below it is edit,delete and add new.
Option Compare Database
Option Explicit
Private Saved As Boolean



Private Sub clearbutton_Click()
DoCmd.GoToRecord , , acNewRec
End Sub

Private Sub cancel_Click()
Me.Undo
End Sub

Private Sub Combo131_BeforeUpdate(cancel As Integer)
If Combo131.Value = "HR" Then
    Call GetCount("HR")
        If hrcount = 7 Then
            MsgBox "you have already reached the limit, choose another department or will be assigned"
            cancel = True
            Me.Combo131.Undo
        End If
End If
If Combo131.Value = "IT" Then
    Call GetCount("IT")
        If itcount = 10 Then
            MsgBox "you have already reached the limit, choose another department or will be assigned"
            cancel = True
            Me.Combo131.Undo
        End If
End If
End Sub

Private Sub Form_BeforeUpdate(cancel As Integer)
Dim Response As Integer
If Saved = False Then
    Response = MsgBox("Do you want to save the changes on this record?", vbYesNo, "Save Changes?")
    If Response = vbNo Then
       Me.Undo
    End If
    
    Call AuditChangesSub("ID", "edit")
    
    Me.save.Enabled = False
End If
End Sub

Private Sub Form_Load()
Me.AllowEdits = False
End Sub

Private Sub showall_Click()
Dim strsearch As String
Call edit_Click
strsearch = "SELECT * from trainingperiod "
Me.RecordSource = strsearch
Me.txtsearch.Value = ""

End Sub

Private Sub search_Click()
Dim strsearch As String
Dim strtext As String
strtext = Me.txtsearch.Value
strsearch = "SELECT * from trainingperiod where([full name] like ""*" & strtext & "*"" or [employee id] like ""*" & strtext & "*"")"
Me.RecordSource = strsearch
Me.txtsearch.Value = ""

End Sub

Private Sub save_Click()
    Call AuditChangesSub("ID", "edit")
    Saved = True
    DoCmd.RunCommand (acCmdSaveRecord)
    Me.save.Enabled = False
    Saved = False
End Sub

Private Sub edit_Click()
Me.AllowEdits = True
End Sub

Private Sub delete_Click()
    
    Dim strsearch As String
    Dim strtext As String
    strtext = (Me.txtsearch.Value)
    If IsNull(Me.txtsearch.Value) Then
         'strtext = Me.CurrentRecord
         Call edit_Click
         If MsgBox("are you sure you want to delete the record", vbYesNo) = vbYes Then
            DoCmd.SetWarnings False
             Call AuditChangesSub("ID", "delete")
            DoCmd.RunCommand acCmdDeleteRecord
            Me.Requery
           
            
        End If
    ElseIf MsgBox("are you sure you want to delete the record", vbYesNo) = vbYes Then
        'strsearch = "DELETE * from trainingperiod where [employee id]= '" + strtext + "'"
        DoCmd.SetWarnings False
        Call AuditChangesSub("ID", "delete")
        DoCmd.RunCommand acCmdDeleteRecord
        Me.Requery
        
        
    End If
    Me.txtsearch.Value = ""
    
End Sub
Private Sub Form_Unload(cancel As Integer)
    Me.Undo
End Sub

Private Sub Form_Error(DataErr As Integer, Response As Integer)
    If DataErr = 2169 Then
        Response = True
    End If
End Sub

Private Sub txtsearch_Click()
    Call edit_Click
End Sub

Private Sub Form_Dirty(cancel As Integer)
    Me.save.Enabled = True
End Sub


CHill60

Было бы неплохо, если бы вы действительно поделились тем, что это было за решение

muneermohd9690

я суммировал это решение

CHill60

Я заметил, что кто-то понизил вас, не объяснив почему. Я чувствую, что это немного сурово, учитывая, что я попросил вас поделиться решением, поэтому я поддержал это с 5

muneermohd9690

спасибо за голосование CHill60.если кому-то нужно больше объяснений для решения,я хотел бы помочь.